wiki update

This commit is contained in:
k
2026-09-21 11:38:19 +02:00
parent 56628fa103
commit d05dad2e48
6 changed files with 40 additions and 2 deletions
+3
View File
@@ -10,6 +10,9 @@ SESSION_TTL_HOURS=720
# Data dir: holds kisassistant.db (SQLite: users, sessions, chats, shares) # Data dir: holds kisassistant.db (SQLite: users, sessions, chats, shares)
DATA_DIR=./data DATA_DIR=./data
# Public docs wiki (Gitea wiki pages of this repo). GET /wiki redirects here.
WIKI_URL=https://git.kisakay.com/k/chat/wiki
# --- rate limit on /api/auth/login (per IP, sliding window) --- # --- rate limit on /api/auth/login (per IP, sliding window) ---
RATE_LIMIT_MAX=5 RATE_LIMIT_MAX=5
RATE_LIMIT_WINDOW_MIN=10 RATE_LIMIT_WINDOW_MIN=10
+20
View File
@@ -0,0 +1,20 @@
fait en sorte de pouvoir upload un avatar (Servir un cdn en local via fichier upload sur le serveur dans un dossier à côté de la codebase)
cdn comme sa
http<remote>/cdn/<avatar>/<id of the account>.<extension>
Extension authorisé ONLY:
jpg/jpeg/webp/png
BLACKLISTE SYSTÈMATHIQUEMENT LE RESTE.
Pas que un detect typeFile avec l'extension.
Logique propre de détection du fichier *magic byte, looking bytes, etc*
Changer l 'avatar à plusieurs règles:
Rate-limit per change / per account de:
5 fois maximum en 2 heures
(window time: 2 hours, max count 5)
file length maxi: 5MB
SYSTEM DE CHANGEMENT DE MDP:
+1
View File
@@ -10,6 +10,7 @@ Copy `.env.example` to `.env`. Full list:
| `APP_PASSWORD` | *(required)* | **admin** access key — generate with `openssl rand -base64 24` | | `APP_PASSWORD` | *(required)* | **admin** access key — generate with `openssl rand -base64 24` |
| `SESSION_TTL_HOURS` | `720` | Bearer session lifetime (30 days) | | `SESSION_TTL_HOURS` | `720` | Bearer session lifetime (30 days) |
| `DATA_DIR` | `./data` | holds `kisassistant.db` (SQLite) | | `DATA_DIR` | `./data` | holds `kisassistant.db` (SQLite) |
| `WIKI_URL` | `https://git.kisakay.com/k/chat/wiki` | remote docs wiki — `GET /wiki` redirects (302) there |
| `RATE_LIMIT_MAX` / `RATE_LIMIT_WINDOW_MIN` | `5` / `10` | login rate limit per IP | | `RATE_LIMIT_MAX` / `RATE_LIMIT_WINDOW_MIN` | `5` / `10` | login rate limit per IP |
| `OLLAMA_HOST` / `OLLAMA_ENABLED` | `http://10.66.66.4:11434` / `true` | local-model driver | | `OLLAMA_HOST` / `OLLAMA_ENABLED` | `http://10.66.66.4:11434` / `true` | local-model driver |
| `MISTRAL_*`, `DEEPSEEK_*`, `ANTHROPIC_*`, `OPENAI_*` | disabled | API drivers: set `*_ENABLED=true` **and** `*_API_KEY` | | `MISTRAL_*`, `DEEPSEEK_*`, `ANTHROPIC_*`, `OPENAI_*` | disabled | API drivers: set `*_ENABLED=true` **and** `*_API_KEY` |
+7 -2
View File
@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { Bot, Cpu, PanelLeftOpen, SendHorizontal, Share2, User as UserIcon } from "lucide-react"; import { BookOpen, Bot, Cpu, PanelLeftOpen, SendHorizontal, Share2, User as UserIcon } from "lucide-react";
import type { ChatMessage, Conversation, DriverModel, User } from "../lib/types.ts"; import type { ChatMessage, Conversation, DriverModel, User } from "../lib/types.ts";
import { Avatar, IconButton, LOGO_URL, Logo, Picker, type PickerGroup, Spinner } from "./ui.tsx"; import { Avatar, IconButton, LOGO_URL, Logo, Picker, type PickerGroup, Spinner } from "./ui.tsx";
import { Markdown } from "./Markdown.tsx"; import { Markdown } from "./Markdown.tsx";
@@ -180,7 +180,12 @@ export function Chat({
<SendHorizontal size={17} /> <SendHorizontal size={17} />
</button> </button>
</form> </form>
<p className="py-2 text-center text-xs opacity-50">No cookies — a Bearer key is stored in this browser only.</p> <p className="py-2 text-center text-xs opacity-50">
<a href="/wiki" target="_blank" rel="noreferrer" className="inline-flex items-center gap-1 underline-offset-2 hover:underline">
<BookOpen size={12} />
Wiki & docs
</a>
</p>
</div> </div>
</div> </div>
); );
+4
View File
@@ -37,6 +37,10 @@ export const config = {
openaiApiKey: env("OPENAI_API_KEY", ""), openaiApiKey: env("OPENAI_API_KEY", ""),
openaiEnabled: envBool("OPENAI_ENABLED", false), openaiEnabled: envBool("OPENAI_ENABLED", false),
// Public docs wiki (served by the hosted git forge, e.g. Gitea wiki pages).
// The app redirects GET /wiki there (302) so the target stays configurable.
wikiUrl: env("WIKI_URL", "https://git.kisakay.com/k/chat/wiki"),
}; };
export function assertConfig(): void { export function assertConfig(): void {
+5
View File
@@ -133,6 +133,11 @@ const server = Bun.serve({
}); });
} }
// --- public: /wiki redirects to the remote docs wiki (git forge) ---
if ((path === "/wiki" || path === "/wiki/") && req.method === "GET") {
return Response.redirect(config.wikiUrl, 302);
}
// --- auth: login (rate limited) --- // --- auth: login (rate limited) ---
if (path === "/api/auth/login" && req.method === "POST") { if (path === "/api/auth/login" && req.method === "POST") {
const ip = clientIp(req, server); const ip = clientIp(req, server);