docs(admin): fold admin-origin CORS into phase 3a Task 1
This commit is contained in:
@@ -60,16 +60,23 @@ apps/admin/ NEW workspace (mirror apps/worker)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Task 1: Backend — `role` on `/api/me`
|
### Task 1: Backend — `role` on `/api/me` + allow the admin origin (CORS)
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `packages/shared/src/index.ts` (PublicUser)
|
- Modify: `packages/shared/src/index.ts` (PublicUser)
|
||||||
- Modify: `apps/api/src/routes/me.ts`
|
- Modify: `apps/api/src/routes/me.ts`
|
||||||
- Test: `apps/api/test/me.test.ts` (extend; or `apps/api/src/routes/me.test.ts` — match
|
- Modify: `apps/api/src/env.ts` (default `WEB_ORIGINS`), `apps/api/.env.example` (comment +
|
||||||
where existing route tests live)
|
default `CORS_ORIGINS`)
|
||||||
|
- Test: `apps/api/test/me.test.ts` (extend), `apps/api/test/cors.test.ts` (extend)
|
||||||
|
|
||||||
**Interfaces:**
|
**Interfaces:**
|
||||||
- Produces: `PublicUser` now has `role: Role`; `MeResponse.user.role` is `'worker' | 'admin'`.
|
- Produces: `PublicUser` now has `role: Role`; `MeResponse.user.role` is `'worker' | 'admin'`.
|
||||||
|
The default CORS/trustedOrigins list includes the admin dev origin `http://localhost:5174`.
|
||||||
|
|
||||||
|
**Why CORS:** the admin app runs on dev port 5174 and calls the API on :3000 cross-origin.
|
||||||
|
`env.WEB_ORIGINS` (used for both `hono/cors` and better-auth `trustedOrigins`) currently
|
||||||
|
defaults to only `http://localhost:5173`, so without this the admin app's sign-in and every
|
||||||
|
request are blocked in the browser.
|
||||||
|
|
||||||
- [ ] **Step 1: Write/extend the failing test.** Using the test helpers
|
- [ ] **Step 1: Write/extend the failing test.** Using the test helpers
|
||||||
(`apps/api/test/helpers.ts`: `createTestUser`, `authToken`/`bearer`), assert that
|
(`apps/api/test/helpers.ts`: `createTestUser`, `authToken`/`bearer`), assert that
|
||||||
@@ -92,10 +99,16 @@ export const PublicUser = z.object({
|
|||||||
- [ ] **Step 4: Return `role` from the route.** In `apps/api/src/routes/me.ts`, add to the
|
- [ ] **Step 4: Return `role` from the route.** In `apps/api/src/routes/me.ts`, add to the
|
||||||
`user` body: `role: ((session.user as { role?: string | null }).role ?? 'worker') as Role`
|
`user` body: `role: ((session.user as { role?: string | null }).role ?? 'worker') as Role`
|
||||||
(import `Role`/`MeResponse` type from `@solelog/shared`). Keep the `MeResponse` typing.
|
(import `Role`/`MeResponse` type from `@solelog/shared`). Keep the `MeResponse` typing.
|
||||||
- [ ] **Step 5: Run tests — pass.** Also run `yarn workspace @solelog/api typecheck`.
|
- [ ] **Step 5: CORS — allow the admin origin.** Add `http://localhost:5174` to the
|
||||||
- [ ] **Step 6: Confirm worker app unaffected** — `yarn workspace @solelog/worker test`
|
default `WEB_ORIGINS` array in `apps/api/src/env.ts`
|
||||||
|
(`['http://localhost:5173', 'http://localhost:5174']`) and to the `CORS_ORIGINS=` line +
|
||||||
|
comment in `apps/api/.env.example`. Extend `apps/api/test/cors.test.ts` with a case
|
||||||
|
asserting the preflight allows `http://localhost:5174` (parametrize or add a second
|
||||||
|
origin assertion). Run the cors test — green.
|
||||||
|
- [ ] **Step 6: Run tests — pass.** Also run `yarn workspace @solelog/api typecheck`.
|
||||||
|
- [ ] **Step 7: Confirm worker app unaffected** — `yarn workspace @solelog/worker test`
|
||||||
still green (it ignores the extra field).
|
still green (it ignores the extra field).
|
||||||
- [ ] **Step 7: Commit** — `feat(api): include role in /api/me response`.
|
- [ ] **Step 8: Commit** — `feat(api): include role in /api/me + allow admin origin in CORS`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -48,12 +48,16 @@ The admin app is a **client only** — it talks to the existing backend over HTT
|
|||||||
bearer token. No DB access. It mirrors `apps/worker`'s toolchain and conventions exactly
|
bearer token. No DB access. It mirrors `apps/worker`'s toolchain and conventions exactly
|
||||||
so the build can copy proven patterns.
|
so the build can copy proven patterns.
|
||||||
|
|
||||||
### Backend change (the only one in 3a)
|
### Backend changes (minimal, in 3a)
|
||||||
|
|
||||||
- `packages/shared/src/index.ts`: add `role: Role` to `PublicUser` (so `MeResponse.user`
|
- `packages/shared/src/index.ts`: add `role: Role` to `PublicUser` (so `MeResponse.user`
|
||||||
carries it).
|
carries it).
|
||||||
- `apps/api/src/routes/me.ts`: include `role` in the response (read from the session user,
|
- `apps/api/src/routes/me.ts`: include `role` in the response (read from the session user,
|
||||||
default `'worker'`). The worker app ignores the extra field — no worker change needed.
|
default `'worker'`). The worker app ignores the extra field — no worker change needed.
|
||||||
|
- `apps/api/src/env.ts` + `.env.example`: add `http://localhost:5174` (the admin dev
|
||||||
|
origin) to the default `WEB_ORIGINS` / `CORS_ORIGINS`. Required because `WEB_ORIGINS`
|
||||||
|
drives both `hono/cors` and better-auth `trustedOrigins`; the admin app at :5174 calls
|
||||||
|
the API at :3000 cross-origin and would otherwise be blocked.
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user