You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
Copy file name to clipboardExpand all lines: docs/implementation-plans/goals-backend-questions.md
+6-5Lines changed: 6 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -153,10 +153,11 @@ GET /goals/{id}/sessions — List sessions that discussed a goal
153
153
- Migration needs to populate `coaching_relationship_id` for existing goals (derive from `coaching_sessions.coaching_relationship_id`)
154
154
155
155
**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`)
158
158
- (c) link/unlink a goal from a session: `POST/DELETE /coaching_sessions_goals` — direct
159
159
- (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`
160
161
161
162
### Additional decisions made alongside Q1
162
163
@@ -170,14 +171,14 @@ GET /goals/{id}/sessions — List sessions that discussed a goal
170
171
-**Join table backfill:** Existing data populated from current `coaching_session_id` relationships
171
172
-**`DELETE /goals/{id}`:** Confirmed and included in backend PR2
172
173
-**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`
173
175
174
176
### PR2 coordinated deploy (breaking change)
175
177
176
178
PR2 renames `coaching_session_id` → `created_in_session_id`, which is a **breaking change** requiring simultaneous frontend deployment:
- GET `/goals` query param: `coaching_session_id` → `created_in_session_id`
179
180
-`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)
| 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|
355
356
| Q2 | Goal FK on actions |**Option A: add FK**| Nullable `goal_id` on actions, ON DELETE SET NULL |
356
357
| Q3 | SSE events |**Renamed + 2 new**|`goal_*` events, `coaching_session_goal_created/deleted`; health sync on read with dynamic heuristics when `target_date` set |
Copy file name to clipboardExpand all lines: docs/implementation-plans/goals-feature-master-plan.md
+2-3Lines changed: 2 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -63,7 +63,7 @@ All four architectural questions have been resolved with the backend team. These
63
63
64
64
| Endpoint | Method | Purpose | Status |
65
65
|---|---|---|---|
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) |
67
67
|`GET /users/{id}/goals`| GET | List all goals for a user | Exists (needs `status`, `coaching_relationship_id` filter params) |
- GET `/goals` query param: `coaching_session_id` → `created_in_session_id`
124
123
-`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)
0 commit comments