Spec updates
This commit is contained in:
parent
b0c749b17d
commit
52649e812a
1 changed files with 40 additions and 61 deletions
101
frontend-spec.md
101
frontend-spec.md
|
|
@ -104,39 +104,27 @@ This plan is adapted to the existing codebase, focusing on refactoring rather th
|
|||
|
||||
---
|
||||
|
||||
## 0. Current State (Nov 2025) and Gap Analysis
|
||||
## 0. Current State (Nov 1, 2025)
|
||||
|
||||
Current implementation is single-tenant with username-based login and no household context.
|
||||
All core features are migrated to multi-tenancy with path-scoped endpoints and token-based auth. The codebase no longer uses the `X-Household-Slug` header. Tests and type checks are fully green.
|
||||
|
||||
What exists today
|
||||
What exists now
|
||||
- Auth
|
||||
- `src/api/auth.ts`: username login (`login(username: string)`), `currentUser()` via cookie `user_id`.
|
||||
- `src/composables/useAuth.ts`: stores `Person | null`, exposes `login(username)` and `loadUser()`.
|
||||
- `src/components/LoginPage.vue`: lists persons and logs in by selected person name.
|
||||
- `src/api/auth.ts`: email/password login and register; token-only refresh in `currentUser()` which then loads `/api/v1/users/me/households`.
|
||||
- `src/composables/useAuth.ts`: manages `user`, `households`, and `activeHousehold`; exposes login/logout/createAccount and `fetchHouseholds()`.
|
||||
- Routing
|
||||
- `src/router/index.ts`: flat routes (`/recipes`, `/shopping`, `/mealplan`); no `/:householdSlug` nesting or redirects.
|
||||
- Guard checks `requiresAuth` only; no household awareness.
|
||||
- `src/router/index.ts`: feature-flagged nesting under `/:householdSlug/...`; public routes include `/create-account`, `/welcome`, and `/invitations/accept`.
|
||||
- Guard fetches households, redirects root `/` to the first household's `mealplan`, and uses memory history in tests (hash in browser).
|
||||
- SDK/API
|
||||
- `src/api/sdk.ts`: calls `/api/v1/...` without household context.
|
||||
- Generated OpenAPI types do not include household slug in paths; shapes are single-tenant.
|
||||
- `src/api/sdk.ts`: recipes, meals, and shopping are migrated to `/api/v1/households/{householdSlug}/...` typed endpoints. Persons and parse use temporary raw fetch endpoints where OpenAPI lacks coverage.
|
||||
- `src/api/client.ts`: Authorization header provider only; household header injection removed.
|
||||
- Domain & UI
|
||||
- Identity revolves around `Person`; no household model, switcher, or settings views.
|
||||
- Member arrays (`chefs`, `consumers`, `cleanup`) normalized to MemberRef `{ id, displayName }` with decoders handling legacy shapes gracefully.
|
||||
- Invitation Accept flow implemented; Household Settings supports sending invitations and listing members (members via temporary raw fetch path-scoped endpoint until typed spec lands).
|
||||
|
||||
Gaps vs requirements
|
||||
- Authentication & onboarding
|
||||
- Implemented: JWT `loginWithPassword`, `logout`, account creation via `createAccount` with token provider wiring.
|
||||
- UI: `LoginPage.vue` shows email/password form under feature flag; `CreateAccount.vue` view implemented; `Welcome.vue` creates household; Invitation Accept implemented; Google OAuth pending.
|
||||
- Routing & URL-based tenancy
|
||||
- Partial: Feature-flagged nesting implemented; still need guard logic for fetching households and redirects.
|
||||
- `useHousehold.ts` and `HouseholdSwitcher.vue` added; further wiring to fetch households pending.
|
||||
- API boundary
|
||||
- No household scoping passed to backend. Need a typed strategy (prefer header parameter) without breaking OpenAPI typing.
|
||||
- Cleanup
|
||||
- `persons` used across login and tests; must be deprecated in favor of authenticated `user` and their households.
|
||||
|
||||
Assumptions and constraints
|
||||
- Preserve strict TS (no `any`/`unknown` in app code) and keep OpenAPI as source of truth.
|
||||
- Do not rewrite typed API paths in code; prefer header or OpenAPI param for household scoping.
|
||||
Status of tests and typing
|
||||
- All tests pass: 27 files, 48 tests.
|
||||
- `tsc` and `vue-tsc` pass with no errors.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -144,19 +132,11 @@ Assumptions and constraints
|
|||
|
||||
The backend OpenAPI has been updated and now exposes `householdSlug` as a path parameter for scoped endpoints (recipes, meals, shopping, invitations, whoami). Auth endpoints are fully typed (login/register/refresh/logout). Invitation acceptance remains a global endpoint (`/api/v1/invitations/accept`) with a typed operation.
|
||||
|
||||
Implications and actions:
|
||||
- Replace the temporary `X-Household-Slug` header injection with typed path parameters.
|
||||
- Migrate all API calls to pass `{ params: { path: { householdSlug } } }` where required.
|
||||
- Remove `setHouseholdSlugProvider` usage once the migration is complete.
|
||||
- Auth refresh now returns only `{ accessToken, tokenType }` (no `user` object). The `currentUser()` flow must:
|
||||
1) Call refresh to obtain a token and set the Authorization provider.
|
||||
2) Load user/household context via typed endpoints (e.g., `GET /api/v1/users/me/households`).
|
||||
3) Optional: Use `GET /api/v1/households/{householdSlug}/whoami` to validate membership for the active route.
|
||||
- Invitations:
|
||||
- Create invitation is now typed at `POST /api/v1/households/{householdSlug}/invitations`.
|
||||
- Accept invitation is typed at `POST /api/v1/invitations/accept`.
|
||||
- Remove temporary raw fetch usage for invitations and switch to the generated client.
|
||||
- Household members listing endpoint is still not present in OpenAPI; continue using the temporary fetch wrapper until the backend exposes it.
|
||||
Implications and actions (completed):
|
||||
- Removed `X-Household-Slug` and migrated to typed path parameters across recipes, meals, and shopping.
|
||||
- `currentUser()` updated to token-only refresh and household loading.
|
||||
- Invitations: sending is typed under household scope; accept is typed globally.
|
||||
- Members listing is temporarily fetched via a path-scoped raw endpoint until OpenAPI includes it.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -166,7 +146,7 @@ Progress Log (Nov 1, 2025)
|
|||
- Implemented `loginWithPassword`, `logout`, and stubs in `src/api/auth.ts` to satisfy tests.
|
||||
- Refactored `useAuth` to add households and activeHousehold state, plus `loginWithPassword` and `logout`. Tests added and passing.
|
||||
- Added router tests and implemented feature-flagged nested routes and new public routes. Placeholders for onboarding/invitations added.
|
||||
- Implemented `useHousehold.ts`, header + auth providers in API client, minimal `HouseholdSwitcher.vue`, and mounted it. Added a header injection test.
|
||||
- Implemented `useHousehold.ts`, Authorization provider in API client, minimal `HouseholdSwitcher.vue`, and mounted it. Replaced header injection test with path-scoped assertion.
|
||||
- Implemented JWT login/register in `auth.ts` and wired token to client provider. `useAuth` updated with households fetching. `currentUser` refactored to token-only refresh plus households load.
|
||||
- Router guard updated to handle public/multitenant routing and redirects.
|
||||
- Added `useAuth.createAccount` with state update and tests for it; implemented `CreateAccount.vue` with form and navigation.
|
||||
|
|
@ -174,11 +154,11 @@ Progress Log (Nov 1, 2025)
|
|||
- Next: Implement Household Settings (invite members form), then remove legacy Person UI.
|
||||
- Added a Settings link to `HouseholdSwitcher.vue` to surface the `household-settings` route for easier discovery.
|
||||
- Implemented Household Settings invite form and members list UI. `src/views/HouseholdSettings.vue` now loads members via a temporary `listMembers()` in `src/api/households.ts` using the raw fetch helper. When the backend exposes a typed endpoint, we will swap to the generated client.
|
||||
- Fixed router tests by using memory history in non-browser environments to avoid relying on `window.location` during unit tests.
|
||||
- Router uses memory history in tests to avoid relying on `window.location`.
|
||||
- Backend updated OpenAPI and codegen has been run:
|
||||
- Many endpoints are now path-scoped with `{householdSlug}` (recipes, meals, shopping, invitations (create), whoami).
|
||||
- Auth endpoints (login/register/refresh/logout) are fully typed; `refresh` returns only `{ accessToken, tokenType }`.
|
||||
- Action: begin migrating API usage to typed path parameters and remove temporary header injection and fetch helpers.
|
||||
- Completed migration to typed path parameters; header injection removed; only small raw fetch helpers remain for endpoints not yet in OpenAPI (persons, parse, members list).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -208,13 +188,12 @@ Router
|
|||
|
||||
API client
|
||||
- `src/api/client.ts`:
|
||||
- Previous: header injection (`X-Household-Slug`) from a configurable getter to scope requests.
|
||||
- Now: migrate calls to use typed `{ params: { path: { householdSlug } } }` and remove the `X-Household-Slug` header provider.
|
||||
- Authorization provider remains as-is, fed by the JWT token from login/refresh.
|
||||
- Uses typed `{ params: { path: { householdSlug } } }` across SDK; `X-Household-Slug` header provider removed.
|
||||
- Authorization provider remains as-is, fed by JWT token from login/refresh.
|
||||
|
||||
SDK
|
||||
- `src/api/sdk.ts`:
|
||||
- No path changes; ensure all calls work with new auth and household header.
|
||||
- Recipes, meals, shopping fully path-scoped to households. Persons/parse remain via raw fetch until typed coverage.
|
||||
|
||||
UI
|
||||
- Login Page: Refactored to show email/password form when multitenant flag is enabled; legacy person list retained otherwise. Link to Create Account added.
|
||||
|
|
@ -224,10 +203,9 @@ UI
|
|||
- Adjust pages that call SDK/API to pass `{ householdSlug }` path params once client services are migrated.
|
||||
|
||||
Tests
|
||||
- Update MSW handlers/tests to assume JWT auth and household header.
|
||||
- Add tests for router guards, invitation acceptance, and household switching.
|
||||
- Add API tests for invitations (accept/send) and members listing header behavior. Router tests run under memory history in tests.
|
||||
- Update tests to assert that calls pass `householdSlug` via typed params instead of relying on an injected header.
|
||||
- MSW handlers updated for path-scoped endpoints; Authorization header assertions retained where relevant.
|
||||
- Router tests run under memory history.
|
||||
- Replaced header injection test with path-scoped recipe list test.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -245,24 +223,25 @@ Tests
|
|||
|
||||
## Migration Plan & Feature Flag
|
||||
|
||||
- Optional `MULTITENANT_ENABLED` flag for staged rollout of routes and UI.
|
||||
- Keep legacy login until backend endpoints are ready; hide persons UI once households exist for a user.
|
||||
- `VUE_APP_MULTITENANT_ENABLED` flag controls nested household routes. With the migration complete, keep this flag for rollout control; default can be enabled once backend is stable across environments.
|
||||
|
||||
---
|
||||
|
||||
## Acceptance Criteria (Summary)
|
||||
|
||||
- Users can create accounts, login (email/password, Google), logout, and refresh sessions.
|
||||
- Users can create accounts, login (email/password), logout, and refresh sessions (token-only).
|
||||
- All routes operate under `/:householdSlug` with correct redirects and deep link support.
|
||||
- Active household is selectable and visible; API calls are correctly scoped.
|
||||
- Invitation token acceptance adds membership and navigates to the household dashboard.
|
||||
- Legacy persons login removed from UI; tests updated and passing.
|
||||
- Active household is selectable and visible; API calls are correctly scoped via path params.
|
||||
- Invitation token acceptance adds membership and navigates appropriately.
|
||||
- Legacy persons identity is no longer used in auth; MemberRef used in meal UIs; tests updated and passing.
|
||||
|
||||
Google OAuth is planned next.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
## Open Questions / Next Steps
|
||||
|
||||
- Backend: path vs header vs cookie for `householdSlug`? Confirm to finalize client strategy.
|
||||
- Exact OpenAPI shapes for `User`, `Household`, `Invitation` endpoints.
|
||||
- Google OAuth flow pattern (token exchange vs redirect).
|
||||
- JWT storage medium per security guidance (cookie vs localStorage).
|
||||
- Add a user profile endpoint and load it post-refresh to populate `currentUser()` with real data instead of a placeholder.
|
||||
- Replace temporary raw fetch calls (persons, parse, members listing) with typed endpoints when available.
|
||||
- Implement Google OAuth login and account creation flows.
|
||||
- Review `MyShoppingPage` usage and remove legacy `getMyShoppingList/saveMyShoppingList` stubs when UI is refactored or removed.
|
||||
|
|
|
|||
Loading…
Reference in a new issue