diff --git a/AGENTS.md b/AGENTS.md index b8660c1..a2e15ce 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,6 +26,11 @@ The product is a private-deployment, project-centered workbench for individual k - Keep task sharing conservative: assignees see the task and only explicitly shared linked objects. - AI must not create official objects without user confirmation. - AI calls must record provider, key type, action, status, and errors. +- Auth session tokens must be signed, expiring bearer tokens; do not accept forgeable `user:` strings. +- HTTP handlers must read the current user from auth middleware and must not hard-code user IDs. +- Generated tasks, notes, and sources from inbox confirmation should retain their source inbox item ID. +- Task sharing must verify that the shared note/source belongs to the same project as the task. +- User AI keys must be encrypted at rest and AI calls should pass through rate-limit checks before provider execution. ## Frontend Rules diff --git a/README.md b/README.md index 36090a1..1ce903c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,14 @@ go run ./cmd/api The web client uses Svelte and TypeScript only. The login shell lets users enter a server IP address or domain name, which is saved as the API base URL. +## Backend Configuration + +- `PORT`: API listen port, default `8080`. +- `DATABASE_URL`: PostgreSQL connection string. Do not commit real credentials. +- `AUTH_SECRET`: HMAC secret for invite and session tokens. +- `SYSTEM_AI_KEY`: optional fallback AI provider key. +- `AI_KEY_ENCRYPTION_SECRET`: secret used to encrypt user AI keys at rest. + ## Verification See `docs/mvp-verification.md` for backend, web, desktop, PostgreSQL, and manual MVP verification steps. diff --git a/apps/web/e2e/project-workbench.spec.ts b/apps/web/e2e/project-workbench.spec.ts index a1f847f..8a2358a 100644 --- a/apps/web/e2e/project-workbench.spec.ts +++ b/apps/web/e2e/project-workbench.spec.ts @@ -7,3 +7,11 @@ test('project workbench shell renders', async ({ page }) => { await expect(page.getByLabel('服务器 IP 或域名')).toBeVisible(); await expect(page.getByLabel('项目总览')).toBeVisible(); }); + +test('inbox suggestions require explicit confirmation', async ({ page }) => { + await page.goto('/'); + await page.getByLabel('选择 跟进报价').check(); + await page.getByRole('button', { name: '创建选中项' }).click(); + + await expect(page.getByText('已选择 1 项')).toBeVisible(); +}); diff --git a/apps/web/src/app/App.svelte b/apps/web/src/app/App.svelte index ffeeb8d..a4c6389 100644 --- a/apps/web/src/app/App.svelte +++ b/apps/web/src/app/App.svelte @@ -1,12 +1,60 @@ @@ -14,17 +62,15 @@
- + +
+

AI 整理建议

+ +

已选择 {selectedSuggestionCount} 项

+
diff --git a/apps/web/src/features/inbox/SuggestionList.svelte b/apps/web/src/features/inbox/SuggestionList.svelte index b95f0db..913d06b 100644 --- a/apps/web/src/features/inbox/SuggestionList.svelte +++ b/apps/web/src/features/inbox/SuggestionList.svelte @@ -1,9 +1,5 @@