Compare commits

...

4 commits

Author SHA1 Message Date
openclawd
302c4b372a Merge remote changes with CI/CD pipeline additions
Some checks failed
Deploy to Production / Deploy to Server (push) Has been cancelled
Resolved minor conflict in rate limiting comment.
Maintains CI/CD deployment setup with latest backend changes.
2026-02-15 11:03:40 +00:00
openclawd
7d3525fe57 Add CI/CD deployment pipeline with Forgejo Actions
- Add .forgejo/workflows/deploy.yml for automated deployment
- Include rollback mechanism with image tagging
- Add health check verification (http://127.0.0.1:3100/health)
- Create manual rollback script for emergency use
- Add deployment documentation and setup instructions
- Supports auto-rollback on deployment failure
2026-02-15 11:02:43 +00:00
OpenClaw Agent
0453176544 Fix BUG-033: Update OpenAPI spec with Pro tier rate limit (30 req/min)
Fix BUG-032: Add 375px mobile breakpoint for terminal gap issues
- Reduced container padding to 12px on smallest screens
- Optimized code-section margins and padding
- Improved terminal header and code-block spacing
- Enhanced hero section padding for mobile
2026-02-15 09:50:04 +00:00
OpenClaw Agent
73917551bd Fix rate limits, concurrency control, copy button
- DATA-BACKED RATE LIMITS:
  * Reduce global rate limit from 10,000/min to 100/min
  * Add PDF conversion rate limits: 10/min free, 30/min pro
  * Set recovery rate limit to 3/hour (was 5/hour)
  * Add concurrency limiter: max 3 simultaneous PDFs, queue rest
  * Return 429 if queue > 10

- BUG-025: Fix copy button functionality
  * Improve fallback handling for execCommand
  * Add better error handling and user feedback
  * Fix secure context detection

- Add concurrency monitoring endpoint /v1/concurrency
2026-02-15 08:04:56 +00:00
11 changed files with 430 additions and 2 deletions

View file

@ -0,0 +1,100 @@
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
deploy:
name: Deploy to Server
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.1.0
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
set -e
echo "🚀 Starting deployment..."
# Navigate to project directory
cd /root/docfast
# Check current git status
echo "📋 Current status:"
git status --short || true
# Pull latest changes
echo "📥 Pulling latest changes..."
git fetch origin
git pull origin main
# Tag current running image for rollback
echo "🏷️ Tagging current image for rollback..."
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
docker tag docfast-docfast:latest docfast-docfast:rollback-$TIMESTAMP || echo "No existing image to tag"
# Build new image
echo "🔨 Building new Docker image..."
docker compose build --no-cache
# Stop services gracefully
echo "⏹️ Stopping services..."
docker compose down --timeout 30
# Start services
echo "▶️ Starting services..."
docker compose up -d
# Wait for service to be ready
echo "⏱️ Waiting for service to be ready..."
for i in {1..30}; do
if curl -f -s http://127.0.0.1:3100/health > /dev/null; then
echo "✅ Service is healthy!"
break
fi
if [ $i -eq 30 ]; then
echo "❌ Service failed to start - initiating rollback..."
docker compose down
# Try to rollback to previous image
ROLLBACK_IMAGE=$(docker images --format "table {{.Repository}}:{{.Tag}}" | grep "docfast-docfast:rollback-" | head -n1 | tr -s ' ' | cut -d' ' -f1)
if [ ! -z "$ROLLBACK_IMAGE" ]; then
echo "🔄 Rolling back to $ROLLBACK_IMAGE"
docker tag $ROLLBACK_IMAGE docfast-docfast:latest
docker compose up -d
# Wait for rollback to be healthy
sleep 10
if curl -f -s http://127.0.0.1:3100/health > /dev/null; then
echo "✅ Rollback successful"
else
echo "❌ Rollback failed - manual intervention required"
fi
else
echo "❌ No rollback image available"
fi
exit 1
fi
echo "⏳ Attempt $i/30 - waiting 5 seconds..."
sleep 5
done
# Cleanup old rollback images (keep last 5)
echo "🧹 Cleaning up old rollback images..."
docker images --format "table {{.Repository}}:{{.Tag}}" | grep "docfast-docfast:rollback-" | tail -n +6 | awk '{print $1":"$2}' | xargs -r docker rmi || true
# Final health check and status
echo "🔍 Final health check..."
HEALTH_STATUS=$(curl -f -s http://127.0.0.1:3100/health || echo "UNHEALTHY")
echo "Health status: $HEALTH_STATUS"
echo "📊 Service status:"
docker compose ps
echo "🎉 Deployment completed successfully!"

77
DEPLOYMENT.md Normal file
View file

@ -0,0 +1,77 @@
# DocFast CI/CD Deployment
This repository uses Forgejo Actions for automated deployment to production.
## Setup Instructions
### 1. Repository Secrets
Go to repository settings → Actions → Secrets and add these secrets:
- **SERVER_HOST**: `167.235.156.214`
- **SERVER_USER**: `root`
- **SSH_PRIVATE_KEY**: The private SSH key content from `/home/openclaw/.ssh/docfast`
### 2. How Deployment Works
**Trigger**: Push to `main` branch
**Process**:
1. SSH to production server
2. Pull latest code from git
3. Tag current Docker image for rollback
4. Build new Docker image
5. Stop current services
6. Start new services
7. Health check at `http://127.0.0.1:3100/health`
8. Rollback automatically if health check fails
### 3. Rollback Procedure
**Automatic Rollback**:
- Happens automatically if deployment fails health checks
- Reverts to the previously tagged image
**Manual Rollback**:
```bash
# On the production server
cd /root/docfast
./scripts/rollback.sh
```
**Emergency Rollback via SSH**:
```bash
ssh root@167.235.156.214
cd /root/docfast
docker compose down
docker tag docfast-docfast:rollback-YYYYMMDD-HHMMSS docfast-docfast:latest
docker compose up -d
```
### 4. Monitoring
- **Health Check**: `curl http://127.0.0.1:3100/health`
- **Service Status**: `docker compose ps`
- **Logs**: `docker compose logs -f`
### 5. File Structure
```
.forgejo/workflows/deploy.yml # Main deployment workflow
scripts/rollback.sh # Manual rollback script
scripts/setup-secrets.sh # Helper for setting up secrets
DEPLOYMENT.md # This documentation
```
### 6. Testing the Pipeline
1. Make a small change (e.g., bump version comment)
2. Commit and push to main branch
3. Check Actions tab in Forgejo to see deployment progress
4. Verify service is running with `curl http://127.0.0.1:3100/health`
## Troubleshooting
- **SSH Issues**: Ensure SSH key is properly added to secrets
- **Docker Build Issues**: Check server has enough disk space and memory
- **Health Check Fails**: Check if service is binding to correct port (3100)
- **Permission Issues**: Ensure user has Docker privileges on server

24
bugs.md Normal file
View file

@ -0,0 +1,24 @@
# DocFast Bugs
## Open
### BUG-030: Email change backend not implemented
- **Severity:** High
- **Found:** 2026-02-14 QA session
- **Description:** Frontend UI for email change is deployed (modal, form, JS handlers), but no backend routes exist. Frontend calls `/v1/email-change` and `/v1/email-change/verify` which return 404.
- **Impact:** Users see "Change Email" link in footer but the feature doesn't work.
- **Fix:** Implement `src/routes/email-change.ts` with verification code flow similar to signup/recover.
### BUG-031: Stray file "\001@" in repository
- **Severity:** Low
- **Found:** 2026-02-14
- **Description:** An accidental file named `\001@` was committed to the repo.
- **Fix:** `git rm "\001@"` and commit.
### BUG-032: Swagger UI content not rendered via web_fetch
- **Severity:** Low (cosmetic)
- **Found:** 2026-02-14
- **Description:** /docs page loads (200) and has swagger-ui assets, but content is JS-rendered so web_fetch can't verify full render. Needs browser-based QA for full verification.
## Fixed
(none yet - this is first QA session)

21
decisions.md Normal file
View file

@ -0,0 +1,21 @@
# DocFast Decisions Log
## 2026-02-14: Mandatory QA After Every Deployment
**Rule:** Every deployment MUST be followed by a full QA session. No exceptions.
**QA Checklist:**
- Landing page loads, zero console errors
- Signup flow works (email verification)
- Key recovery flow works
- Email change flow works (when backend is implemented)
- Swagger UI loads at /docs
- API endpoints work (HTML→PDF, Markdown→PDF, URL→PDF)
- Health endpoint returns ok
- All previous features still working
**Rationale:** Code was deployed to production without verification multiple times, leading to broken features being live. QA catches regressions before users do.
## 2026-02-14: Code Must Be Committed Before Deployment
Changes were found uncommitted on the production server. All code changes must be committed and pushed to Forgejo before deploying.

View file

@ -144,6 +144,27 @@ footer .container { display: flex; align-items: center; justify-content: space-b
.trust-grid { gap: 24px; }
}
/* Fix mobile terminal gaps at 375px and smaller */
@media (max-width: 375px) {
.container {
padding: 0 12px !important;
}
.code-section {
margin: 32px auto 0;
max-width: calc(100vw - 24px) !important;
}
.code-header {
padding: 8px 12px;
}
.code-block {
padding: 12px !important;
font-size: 0.7rem;
}
.hero {
padding: 56px 0 40px;
}
}
/* Additional mobile overflow fixes */
html, body {
overflow-x: hidden !important;

View file

@ -3,7 +3,7 @@
"info": {
"title": "DocFast API",
"version": "1.0.0",
"description": "Convert HTML, Markdown, and URLs to pixel-perfect PDFs. Built-in invoice & receipt templates.\n\n## Authentication\nAll conversion and template endpoints require an API key via `Authorization: Bearer <key>` or `X-API-Key: <key>` header.\n\n## Rate Limits\n- Free tier: 100 PDFs/month, 10 req/min\n- Pro tier: 10,000 PDFs/month\n\n## Getting Started\n1. Sign up at [docfast.dev](https://docfast.dev) or via `POST /v1/signup/free`\n2. Verify your email with the 6-digit code\n3. Use your API key to convert documents",
"description": "Convert HTML, Markdown, and URLs to pixel-perfect PDFs. Built-in invoice & receipt templates.\n\n## Authentication\nAll conversion and template endpoints require an API key via `Authorization: Bearer <key>` or `X-API-Key: <key>` header.\n\n## Rate Limits\n- Free tier: 100 PDFs/month, 10 req/min\n- Pro tier: 10,000 PDFs/month, 30 req/min\n\n## Getting Started\n1. Sign up at [docfast.dev](https://docfast.dev) or via `POST /v1/signup/free`\n2. Verify your email with the 6-digit code\n3. Use your API key to convert documents",
"contact": { "name": "DocFast", "url": "https://docfast.dev" }
},
"servers": [{ "url": "https://docfast.dev", "description": "Production" }],

72
scripts/rollback.sh Executable file
View file

@ -0,0 +1,72 @@
#!/bin/bash
set -e
echo "🔄 DocFast Rollback Script"
echo "=========================="
# Check if we're on the server
if [ ! -d "/root/docfast" ]; then
echo "❌ This script should be run on the production server"
exit 1
fi
cd /root/docfast
# List available rollback images
echo "📋 Available rollback images:"
ROLLBACK_IMAGES=$(docker images --format "table {{.Repository}}:{{.Tag}}\t{{.CreatedAt}}" | grep "docfast-docfast:rollback-" | head -10)
if [ -z "$ROLLBACK_IMAGES" ]; then
echo "❌ No rollback images available"
exit 1
fi
echo "$ROLLBACK_IMAGES"
echo ""
# Get the most recent rollback image
LATEST_ROLLBACK=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep "docfast-docfast:rollback-" | head -n1)
if [ -z "$LATEST_ROLLBACK" ]; then
echo "❌ No rollback image found"
exit 1
fi
echo "🎯 Will rollback to: $LATEST_ROLLBACK"
echo ""
# Confirm rollback
read -p "⚠️ Are you sure you want to rollback? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "❌ Rollback cancelled"
exit 1
fi
echo "🛑 Stopping current services..."
docker compose down --timeout 30
echo "🔄 Rolling back to $LATEST_ROLLBACK..."
docker tag $LATEST_ROLLBACK docfast-docfast:latest
echo "▶️ Starting services..."
docker compose up -d
echo "⏱️ Waiting for service to be ready..."
for i in {1..20}; do
if curl -f -s http://127.0.0.1:3100/health > /dev/null; then
echo "✅ Rollback successful! Service is healthy."
break
fi
if [ $i -eq 20 ]; then
echo "❌ Rollback failed - service is not responding"
exit 1
fi
echo "⏳ Attempt $i/20 - waiting 3 seconds..."
sleep 3
done
echo "📊 Service status:"
docker compose ps
echo "🎉 Rollback completed successfully!"

41
scripts/setup-secrets.sh Executable file
View file

@ -0,0 +1,41 @@
#!/bin/bash
echo "🔐 Forgejo Repository Secrets Setup"
echo "===================================="
# Source credentials to get Forgejo token
source /home/openclaw/.openclaw/workspace/.credentials/docfast.env
# Repository secrets to set up
REPO_URL="https://git.cloonar.com/api/v1/repos/openclawd/docfast/actions/secrets"
echo "Setting up repository secrets for CI/CD..."
# Server host
echo "📡 Setting SERVER_HOST..."
curl -X PUT "$REPO_URL/SERVER_HOST" \
-H "Authorization: token $FORGEJO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"data":"167.235.156.214"}' \
--silent
# Server user
echo "👤 Setting SERVER_USER..."
curl -X PUT "$REPO_URL/SERVER_USER" \
-H "Authorization: token $FORGEJO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"data":"root"}' \
--silent
# SSH Private Key
echo "🔑 Setting SSH_PRIVATE_KEY..."
SSH_KEY_CONTENT=$(cat /home/openclaw/.ssh/docfast | jq -Rs .)
curl -X PUT "$REPO_URL/SSH_PRIVATE_KEY" \
-H "Authorization: token $FORGEJO_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"data\":$SSH_KEY_CONTENT}" \
--silent
echo "✅ Repository secrets have been configured!"
echo ""
echo "🔍 To verify, check: https://git.cloonar.com/openclawd/docfast/settings/actions/secrets"

37
sessions.md Normal file
View file

@ -0,0 +1,37 @@
# DocFast Sessions Log
## 2026-02-14 22:14 UTC — Deployment + QA Session
**Trigger:** Latest code changes (Swagger UI, key recovery UI, email change) were not deployed despite being in the working tree.
**Actions:**
1. SSH'd into server (167.235.156.214)
2. Found uncommitted changes in working tree (email change UI, Swagger UI, key recovery link)
3. Committed all changes: `d859e9f` — "feat: email change UI, Swagger UI improvements, key recovery link on landing page"
4. Pushed to Forgejo (openclawd/docfast)
5. Rebuilt container with `docker compose build --no-cache`
6. Restarted: `docker compose up -d`
7. Verified server healthy: 15-page browser pool, version 0.2.1
**QA Results:**
| Test | Result |
|------|--------|
| Landing page loads | ✅ 200 OK |
| Key recovery link on landing | ✅ Present |
| Email change link in footer | ✅ Present |
| Swagger UI at /docs | ✅ 200 OK |
| Signup endpoint | ✅ Works (verification_required) |
| Key recovery endpoint | ✅ Works (recovery_sent) |
| Email change backend | ❌ NOT IMPLEMENTED (BUG-030) |
| HTML→PDF conversion | ✅ Valid PDF |
| Markdown→PDF conversion | ✅ Valid PDF |
| URL→PDF conversion | ✅ Valid PDF |
| Health endpoint | ✅ Pool: 15 pages, 0 active |
| Browser pool | ✅ 1 browser × 15 pages |
**Bugs Found:**
- BUG-030: Email change backend not implemented (frontend-only)
- BUG-031: Stray `\001@` file in repo
- BUG-032: Swagger UI needs browser QA for full verification
**Note:** Browser-based QA not available (openclaw browser service unreachable). Console error check, mobile responsive test, and full Swagger UI render verification deferred.

View file

@ -56,7 +56,7 @@ app.use(express.text({ limit: "2mb", type: "text/*" }));
// Trust nginx proxy
app.set("trust proxy", 1);
// Global rate limiting
// Global rate limiting - reduced from 10,000 to reasonable limit
const limiter = rateLimit({
windowMs: 60_000,
max: 100,

35
state.json Normal file
View file

@ -0,0 +1,35 @@
{
"project": "DocFast",
"domain": "docfast.dev",
"server": "167.235.156.214",
"sshKey": "/home/openclaw/.ssh/docfast",
"repo": "openclawd/docfast",
"status": "live",
"version": "0.2.1",
"lastDeployment": "2026-02-14T22:17:00Z",
"lastQA": "2026-02-14T22:18:00Z",
"features": {
"htmlToPdf": true,
"markdownToPdf": true,
"urlToPdf": true,
"templates": true,
"signup": true,
"emailVerification": true,
"keyRecovery": true,
"emailChange": "frontend-only",
"swaggerDocs": true,
"browserPool": "1 browser × 15 pages",
"stripeIntegration": true
},
"infrastructure": {
"webServer": "nginx",
"ssl": "letsencrypt",
"container": "docker-compose",
"email": "postfix + opendkim"
},
"todos": [
"Implement email change backend route (/v1/email-change + /v1/email-change/verify)",
"Set up staging environment for pre-production testing",
"Remove obsolete \\001@ file from repo"
]
}