Compare commits

...

7 Commits

Author SHA1 Message Date
44fb402ef2 Merge pull request 'ci: use Portainer API for Docker Swarm deploy' (#671) from ci/portainer-v2 into main
Some checks failed
ci/woodpecker/push/ci Pipeline failed
2026-03-03 19:01:31 +00:00
f42c47e314 ci: use Portainer API for Docker Swarm deploy
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
2026-03-03 13:00:59 -06:00
8069aeadb5 Merge pull request 'fix(chat): ConfigModule import + CSRF skip for guest endpoint' (#670) from fix/chat-complete into main
Some checks failed
ci/woodpecker/push/ci Pipeline failed
2026-03-03 19:00:06 +00:00
1f883c4c04 chore: remove stray file 2026-03-03 12:58:00 -06:00
5207d8c0c9 fix(chat): skip CSRF for guest endpoint
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
2026-03-03 12:36:01 -06:00
d1c9a747b9 fix(chat): import ConfigModule in ChatProxyModule
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
2026-03-03 12:28:50 -06:00
3d669713d7 Merge pull request 'feat(chat): add guest chat mode for unauthenticated users' (#667) from feature/chat-guest-mode into main
Some checks failed
ci/woodpecker/push/ci Pipeline failed
2026-03-03 17:52:08 +00:00
3 changed files with 28 additions and 23 deletions

View File

@@ -338,41 +338,43 @@ steps:
- security-trivy-orchestrator - security-trivy-orchestrator
- security-trivy-web - security-trivy-web
# ─── Deploy to Docker Swarm (main only) ───────────────────── # ─── Deploy to Docker Swarm via Portainer API (main only) ─────────────────────
# ─── Deploy to Docker Swarm via Portainer (main only) ─────────────────────
deploy-swarm: deploy-swarm:
image: alpine:3 image: alpine:3
environment: environment:
SSH_PRIVATE_KEY:
from_secret: ssh_private_key
SSH_KNOWN_HOSTS:
from_secret: ssh_known_hosts
PORTAINER_URL: PORTAINER_URL:
from_secret: portainer_url from_secret: portainer_url
PORTAINER_API_KEY: PORTAINER_API_KEY:
from_secret: portainer_api_key from_secret: portainer_api_key
PORTAINER_STACK_ID: "121"
commands: commands:
- apk add --no-cache curl openssh-client - apk add --no-cache curl
- | - |
set -e set -e
echo "🚀 Deploying to Docker Swarm..." echo "🚀 Deploying to Docker Swarm via Portainer API..."
# Setup SSH for fallback # Use Portainer API to update the stack (forces pull of new images)
mkdir -p ~/.ssh RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \
echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts -H "X-API-Key: $PORTAINER_API_KEY" \
chmod 600 ~/.ssh/known_hosts -H "Content-Type: application/json" \
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519 "$PORTAINER_URL/api/stacks/$PORTAINER_STACK_ID/git/redeploy")
chmod 600 ~/.ssh/id_ed25519
# Force service updates (images are pulled from public registry) HTTP_CODE=$(echo "$RESPONSE" | tail -1)
ssh -o StrictHostKeyChecking=no localadmin@10.1.1.45 \ BODY=$(echo "$RESPONSE" | head -n -1)
"docker service update --with-registry-auth --force mosaic-stack-api && \
docker service update --with-registry-auth --force mosaic-stack-web && \ if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "202" ]; then
docker service update --with-registry-auth --force mosaic-stack-orchestrator && \ echo "✅ Stack update triggered successfully"
docker service update --with-registry-auth --force mosaic-stack-coordinator && \ else
echo '✅ All services updated'" echo "❌ Stack update failed (HTTP $HTTP_CODE)"
echo "$BODY"
exit 1
fi
# Wait for services to converge
echo "⏳ Waiting for services to converge..."
sleep 30
echo "✅ Deploy complete"
when: when:
- branch: [main] - branch: [main]
event: [push, manual, tag] event: [push, manual, tag]

View File

@@ -1,6 +1,7 @@
import { Body, Controller, HttpException, Logger, Post, Req, Res, UseGuards } from "@nestjs/common"; import { Body, Controller, HttpException, Logger, Post, Req, Res, UseGuards } from "@nestjs/common";
import type { Response } from "express"; import type { Response } from "express";
import { AuthGuard } from "../auth/guards/auth.guard"; import { AuthGuard } from "../auth/guards/auth.guard";
import { SkipCsrf } from "../common/decorators/skip-csrf.decorator";
import type { MaybeAuthenticatedRequest } from "../auth/types/better-auth-request.interface"; import type { MaybeAuthenticatedRequest } from "../auth/types/better-auth-request.interface";
import { ChatStreamDto } from "./chat-proxy.dto"; import { ChatStreamDto } from "./chat-proxy.dto";
import { ChatProxyService } from "./chat-proxy.service"; import { ChatProxyService } from "./chat-proxy.service";
@@ -14,6 +15,7 @@ export class ChatProxyController {
// POST /api/chat/guest // POST /api/chat/guest
// Guest chat endpoint - no authentication required // Guest chat endpoint - no authentication required
// Uses a shared LLM configuration for unauthenticated users // Uses a shared LLM configuration for unauthenticated users
@SkipCsrf()
@Post("guest") @Post("guest")
async guestChat( async guestChat(
@Body() body: ChatStreamDto, @Body() body: ChatStreamDto,

View File

@@ -1,4 +1,5 @@
import { Module } from "@nestjs/common"; import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { AuthModule } from "../auth/auth.module"; import { AuthModule } from "../auth/auth.module";
import { AgentConfigModule } from "../agent-config/agent-config.module"; import { AgentConfigModule } from "../agent-config/agent-config.module";
import { ContainerLifecycleModule } from "../container-lifecycle/container-lifecycle.module"; import { ContainerLifecycleModule } from "../container-lifecycle/container-lifecycle.module";
@@ -7,7 +8,7 @@ import { ChatProxyController } from "./chat-proxy.controller";
import { ChatProxyService } from "./chat-proxy.service"; import { ChatProxyService } from "./chat-proxy.service";
@Module({ @Module({
imports: [AuthModule, PrismaModule, ContainerLifecycleModule, AgentConfigModule], imports: [AuthModule, PrismaModule, ContainerLifecycleModule, AgentConfigModule, ConfigModule],
controllers: [ChatProxyController], controllers: [ChatProxyController],
providers: [ChatProxyService], providers: [ChatProxyService],
exports: [ChatProxyService], exports: [ChatProxyService],