All checks were successful
Depuis /admin/messages, un admin peut créer une issue Forgejo à partir
d'un message utilisateur : bouton « Créer un ticket » → modale pré-remplie
éditable → l'issue est créée via l'API Forgejo et le lien (#N) est
mémorisé sur le message. Première intégration Forgejo d'apps/api.
- Modèle : `forgejoIssueNumber` / `forgejoIssueUrl` sur `ContactMessage`
(migration `20260908130000_contact_message_forgejo_link`, 2 colonnes
nullables, aucun backfill).
- Config : `FORGEJO_BASE_URL` / `FORGEJO_TOKEN` / `FORGEJO_REPO`, toutes
`.optional()` — **fail-closed** (même posture que `ADMIN_JWT_SECRET`) :
bouton masqué + endpoint `503` tant que les trois ne sont pas là.
Documentées dans `.env.example` ; valeurs de test dans `ci.yml`.
- `ForgejoService` (`lib/forgejo/forgejo.service.ts`, singleton `forgejo`) :
`isConfigured()` + `createIssue({ title, body })` → `POST .../issues`,
en-tête `Authorization: token <pat>`, lit `{ number, html_url }` ;
erreur réseau / non-2xx / JSON invalide ⇒ `HttpError 502
FORGEJO_REQUEST_FAILED`.
- `admin-contact` : `POST /admin/api/contact/:id/forgejo-issue`
(`createForgejoIssueFromMessage` — ordre 503 → 404 → 409 → Forgejo →
écriture BDD ; un échec Forgejo ne touche pas la BDD) et
`GET /admin/api/contact/forgejo/status`.
- Contrat partagé : `createForgejoIssueSchema` (title 1–255, body 1–60000),
`ContactMessageAdminView` étendu, `ForgejoIntegrationStatus`, nouveaux
`ErrorCode` (`FORGEJO_NOT_CONFIGURED`=5001, `FORGEJO_REQUEST_FAILED`=5002,
`CONTACT_MESSAGE_ALREADY_LINKED`=4026, `CONTACT_MESSAGE_NOT_FOUND`=4055)
+ labels i18n.
- Front : `MessagesPage` — sonde `forgejo/status` au montage, colonne
« Ticket » (lien `#N` si lié, bouton sinon, « non configurée » sinon),
`CreateForgejoIssueModal` + helpers purs `messages.ts`
(`buildIssueTitle` / `buildIssueBody`).
- Tests : `forgejo.service.test.ts` (stub `globalThis.fetch`),
`admin-contact.test.ts` étendu (nominal / 503 / 404 / 409 / 502 +
ligne intacte / 400), `admin-messages.cy.ts` étendu (modale pré-remplie,
lien après création, masquage si non configuré).
- Docs : `backend-architecture.md`, `batch-cooking-modele.md`.
Closes #81.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
46 lines
2.3 KiB
Text
46 lines
2.3 KiB
Text
NODE_ENV=development
|
|
PORT=3000
|
|
# Match whatever you set in the root .env (POSTGRES_USER/PASSWORD/DB) —
|
|
# do not commit the real value.
|
|
DATABASE_URL="postgresql://changeme:changeme@localhost:5432/batchcooking?schema=public"
|
|
|
|
# Required, no default on purpose — generate your own, e.g.:
|
|
# node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"
|
|
JWT_SECRET=changeme-generate-a-real-random-secret-at-least-32-chars
|
|
|
|
# Optional — defaults shown (see src/config/env.ts)
|
|
# JWT_EXPIRES_IN=7d
|
|
# AUTH_COOKIE_NAME=session
|
|
# CORS_ORIGIN=http://localhost:5173,https://localhost
|
|
# INTENT_SERVICE_BASE_URL=http://localhost:8000
|
|
|
|
# Required — services/tech-step-intent-service must be running locally (see
|
|
# that service's own README) for any recipe save/preview to detect
|
|
# techniques at all. Must match that service's own INTENT_SERVICE_SECRET.
|
|
# Generate your own the same way as JWT_SECRET above.
|
|
INTENT_SERVICE_SECRET=changeme-generate-a-real-random-secret-at-least-32-chars
|
|
|
|
# Only needed if you're running services/tech-step-llm-worker locally —
|
|
# every /internal/tech-steps/* request is rejected outright while unset.
|
|
# Generate your own the same way as JWT_SECRET above; must match the
|
|
# worker's own INTERNAL_WORKER_SECRET.
|
|
# INTERNAL_WORKER_SECRET=changeme-generate-a-real-random-secret-at-least-32-chars
|
|
|
|
# Only needed to use the admin surface (apps/web's /admin/* routes) — every
|
|
# /admin/* request 401s while unset (`requireAdmin` fails closed). MUST be a
|
|
# different value than JWT_SECRET. Generate your own the same way.
|
|
# ADMIN_JWT_SECRET=changeme-a-different-random-secret-at-least-32-chars
|
|
# Read only by `src/scripts/create-admin.ts` when its --email/--password/
|
|
# --name flags are omitted — never by the running server.
|
|
# ADMIN_INITIAL_EMAIL=ops@example.com
|
|
# ADMIN_INITIAL_PASSWORD=changeme-at-least-8-chars
|
|
# ADMIN_INITIAL_NAME=Ops
|
|
|
|
# Only needed to create a Forgejo issue from a contact message
|
|
# (apps/web's /admin/messages, issue #81). The button is hidden and the
|
|
# endpoint answers 503 while any of the three is unset. FORGEJO_TOKEN is a
|
|
# personal access token with the write:issue scope — generate it in Forgejo,
|
|
# never commit the real value.
|
|
# FORGEJO_BASE_URL=https://git.example.com
|
|
# FORGEJO_TOKEN=changeme-a-forgejo-personal-access-token
|
|
# FORGEJO_REPO=owner/repo
|