Skip to content

Commit 2639a98

Browse files
committed
docs: add authorization Option C decision to goals plans
- GET /goals now requires coaching_relationship_id for backend auth - created_in_session_id is display metadata only, not a query filter - For session-linked goals, frontend uses GET /coaching_sessions/{id}/goals - Update API gap table, coordinated deploy warning, and Q1 decisions
1 parent 12edabd commit 2639a98

2 files changed

Lines changed: 8 additions & 8 deletions

File tree

docs/implementation-plans/goals-backend-questions.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,11 @@ GET /goals/{id}/sessions — List sessions that discussed a goal
153153
- Migration needs to populate `coaching_relationship_id` for existing goals (derive from `coaching_sessions.coaching_relationship_id`)
154154

155155
**Frontend impact:**
156-
- (a) list all goals for a relationship: `GET /goals?coaching_relationship_id=X` — works
157-
- (b) list goals linked to a specific session: `GET /coaching_sessions/{id}/goals` — direct query
156+
- (a) list all goals for a relationship: `GET /goals?coaching_relationship_id=X` — works (**required** for auth — Option C confirmed)
157+
- (b) list goals linked to a specific session: `GET /coaching_sessions/{id}/goals` — direct query (used instead of filtering `GET /goals` by `created_in_session_id`)
158158
- (c) link/unlink a goal from a session: `POST/DELETE /coaching_sessions_goals` — direct
159159
- (d) know which sessions discussed a goal: `GET /goals/{id}/sessions` — direct query
160+
- (e) `created_in_session_id` is **display metadata only** (which session originated the goal) — not used as a query filter on `GET /goals`
160161

161162
### Additional decisions made alongside Q1
162163

@@ -170,14 +171,14 @@ GET /goals/{id}/sessions — List sessions that discussed a goal
170171
- **Join table backfill:** Existing data populated from current `coaching_session_id` relationships
171172
- **`DELETE /goals/{id}`:** Confirmed and included in backend PR2
172173
- **MAX=3 per session:** Enforced **frontend-only** — no backend constraint on join table row count
174+
- **Authorization (Option C):** `GET /goals` requires `coaching_relationship_id` — backend protect middleware authorizes through it directly. Frontend never queries goals by `created_in_session_id` alone; for session-linked goals, use `GET /coaching_sessions/{id}/goals`
173175

174176
### PR2 coordinated deploy (breaking change)
175177

176178
PR2 renames `coaching_session_id``created_in_session_id`, which is a **breaking change** requiring simultaneous frontend deployment:
177179
- POST/PUT request bodies: `coaching_session_id``created_in_session_id`
178-
- GET `/goals` query param: `coaching_session_id``created_in_session_id`
179180
- `created_in_session_id` is now nullable
180-
- Protect middleware must check `created_in_session_id` instead of `coaching_session_id`
181+
- **Authorization (Option C confirmed):** `GET /goals` requires `coaching_relationship_id` as a query param — backend protect middleware authorizes through it directly. The frontend will never query goals by `created_in_session_id` alone; for session-linked goals, use `GET /coaching_sessions/{id}/goals` (join table endpoint)
181182

182183
### Goal-session carry-forward workflow (PR3 scope)
183184

@@ -351,7 +352,7 @@ This is a lightweight existence check — no need to return full entities.
351352

352353
| # | Question | Decision | Key Details |
353354
|---|----------|----------|-------------|
354-
| Q1 | Goal scoping model | **Option B: join table** | `goals` table + `coaching_sessions_goals` join table (CASCADE both FKs); `coaching_relationship_id` (NOT NULL, backfill); `created_in_session_id` (nullable); `target_date` (nullable); `DELETE /goals/{id}` confirmed in PR2; MAX=3 frontend-only |
355+
| Q1 | Goal scoping model | **Option B: join table** | `goals` table + `coaching_sessions_goals` join table (CASCADE both FKs); `coaching_relationship_id` (NOT NULL, backfill); `created_in_session_id` (nullable); `target_date` (nullable); `DELETE /goals/{id}` confirmed in PR2; MAX=3 frontend-only; **auth: Option C**`GET /goals` requires `coaching_relationship_id`, middleware authorizes through it directly |
355356
| Q2 | Goal FK on actions | **Option A: add FK** | Nullable `goal_id` on actions, ON DELETE SET NULL |
356357
| Q3 | SSE events | **Renamed + 2 new** | `goal_*` events, `coaching_session_goal_created/deleted`; health sync on read with dynamic heuristics when `target_date` set |
357358
| Q4 | Annotation cleanup | **Option C: both** | SSE real-time + per-entity-type load-time validation endpoints |

docs/implementation-plans/goals-feature-master-plan.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ All four architectural questions have been resolved with the backend team. These
6363

6464
| Endpoint | Method | Purpose | Status |
6565
|---|---|---|---|
66-
| `GET /goals?coaching_session_id=` | GET | List goals for a session | Exists (path renamed from `/overarching_goals`) |
66+
| `GET /goals?coaching_relationship_id=` | GET | List goals for a relationship | Exists (path renamed from `/overarching_goals`; `coaching_relationship_id` now required for auth — Option C) |
6767
| `GET /users/{id}/goals` | GET | List all goals for a user | Exists (needs `status`, `coaching_relationship_id` filter params) |
6868
| `GET /goals/{id}` | GET | Single goal | Exists |
6969
| `POST /goals` | POST | Create goal | Exists (body needs `coaching_relationship_id`) |
@@ -120,9 +120,8 @@ The backend team has committed to a 5-PR implementation plan:
120120

121121
**PR2 is a breaking change** requiring simultaneous frontend deployment. The rename of `coaching_session_id``created_in_session_id` affects:
122122
- POST/PUT request bodies: `coaching_session_id``created_in_session_id`
123-
- GET `/goals` query param: `coaching_session_id``created_in_session_id`
124123
- `created_in_session_id` is now **nullable** (goals can be created outside a session context)
125-
- Protect middleware must check `created_in_session_id` instead of `coaching_session_id`
124+
- **Authorization (Option C confirmed):** `GET /goals` now requires `coaching_relationship_id` as a query param — backend protect middleware authorizes through it directly. The frontend will never query goals by `created_in_session_id` alone; for session-linked goals, use `GET /coaching_sessions/{id}/goals` (join table endpoint)
126125

127126
### Goal-Session Carry-Forward Workflow (PR3 scope)
128127

0 commit comments

Comments
 (0)