Skip to content

Commit 8c0eb63

Browse files
authored
Merge pull request #946 from mnfst/chore/production-readiness-audit
Production readiness audit: security, code quality, CI
2 parents bb3fbec + b7d257e commit 8c0eb63

30 files changed

+1178
-381
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"manifest": patch
3+
---
4+
5+
fix: remove hardcoded fallback secret, restrict trusted origins, rename misleading sha256 to hashKey, sync plugin version, extend ESLint coverage, add CI lint job, set up Husky pre-commit hooks

.github/workflows/ci.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ on:
1010
workflow_dispatch:
1111

1212
jobs:
13+
lint:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
- uses: actions/setup-node@v4
18+
with:
19+
node-version: 22
20+
cache: npm
21+
- run: npm ci
22+
- run: npm run lint
23+
1324
backend-postgres:
1425
name: Backend (PostgreSQL)
1526
runs-on: ubuntu-latest

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
npx lint-staged

CLAUDE.md

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Manifest Development Guidelines
22

3-
Last updated: 2026-02-24
3+
Last updated: 2026-03-02
44

55
## IMPORTANT: Local Mode First
66

@@ -69,8 +69,10 @@ packages/
6969
│ │ │ └── current-user.decorator.ts # @CurrentUser() param decorator
7070
│ │ ├── database/
7171
│ │ │ ├── database.module.ts # TypeORM PostgreSQL config
72-
│ │ │ └── database-seeder.service.ts # Seeds model_pricing + demo data
73-
│ │ ├── entities/ # TypeORM entities (14 files)
72+
│ │ │ ├── database-seeder.service.ts # Seeds model_pricing + demo data
73+
│ │ │ ├── local-bootstrap.service.ts # Seeds local mode (SQLite)
74+
│ │ │ └── datasource.ts # CLI DataSource for migration commands
75+
│ │ ├── entities/ # TypeORM entities (19 files)
7476
│ │ │ ├── tenant.entity.ts # Multi-tenant root
7577
│ │ │ ├── agent.entity.ts # Agent (belongs to tenant)
7678
│ │ │ ├── agent-api-key.entity.ts # OTLP ingest keys (mnfst_*)
@@ -79,7 +81,10 @@ packages/
7981
│ │ │ ├── guards/api-key.guard.ts # X-API-Key header auth (timing-safe)
8082
│ │ │ ├── decorators/public.decorator.ts
8183
│ │ │ ├── dto/range-query.dto.ts
82-
│ │ │ └── utils/range.util.ts
84+
│ │ │ ├── utils/range.util.ts
85+
│ │ │ ├── utils/hash.util.ts # API key hashing (scrypt KDF)
86+
│ │ │ ├── utils/crypto.util.ts # AES-256-GCM encryption
87+
│ │ │ └── utils/sql-dialect.ts # Cross-DB SQL helpers (Postgres/SQLite)
8388
│ │ ├── health/ # @Public() health check
8489
│ │ ├── telemetry/ # POST /api/v1/telemetry (JSON ingestion)
8590
│ │ ├── analytics/ # Dashboard analytics
@@ -88,6 +93,11 @@ packages/
8893
│ │ ├── otlp/ # OTLP ingestion (traces, metrics, logs)
8994
│ │ │ ├── guards/otlp-auth.guard.ts # Bearer token auth (agent API keys)
9095
│ │ │ └── services/api-key.service.ts # Agent onboarding (creates tenant+agent+key)
96+
│ │ ├── routing/ # LLM routing (providers, tiers, proxy)
97+
│ │ ├── model-prices/ # Model pricing management + sync
98+
│ │ ├── notifications/ # Alert rules, email providers, cron
99+
│ │ ├── github/ # GitHub stars endpoint
100+
│ │ ├── sse/ # Server-Sent Events for real-time updates
91101
│ │ └── security/ # GET /api/v1/security
92102
│ └── test/ # E2E tests (supertest)
93103
├── frontend/
@@ -104,7 +114,10 @@ packages/
104114
│ │ │ ├── Overview.tsx # Agent dashboard
105115
│ │ │ ├── MessageLog.tsx # Paginated messages
106116
│ │ │ ├── Account.tsx # User profile (session data)
107-
│ │ │ └── Settings.tsx # Agent settings
117+
│ │ │ ├── Settings.tsx # Agent settings
118+
│ │ │ ├── Routing.tsx # LLM routing config
119+
│ │ │ ├── Notifications.tsx # Alert rule management
120+
│ │ │ └── ModelPrices.tsx # Model pricing table
108121
│ │ ├── services/
109122
│ │ │ ├── auth-client.ts # Better Auth SolidJS client
110123
│ │ │ ├── api.ts # API functions (credentials: include)
@@ -219,6 +232,8 @@ npm run migration:create -- src/database/migrations/Name # Create empty migrati
219232

220233
New migrations must be imported in `database.module.ts` and added to the `migrations` array.
221234

235+
**Important**: Always use unique timestamps for new migrations. Never reuse a timestamp from an existing migration file.
236+
222237
## Authentication Architecture
223238

224239
### Guard Chain
@@ -281,7 +296,18 @@ All analytics queries filter by user via `addTenantFilter(qb, userId)` from `que
281296
| GET | `/api/v1/agents` | Session/API Key | Agent list with sparklines |
282297
| POST | `/api/v1/agents` | Session/API Key | Create agent + OTLP key |
283298
| DELETE | `/api/v1/agents/:name` | Session/API Key | Delete agent |
299+
| GET | `/api/v1/agents/:name/key` | Session/API Key | Get agent OTLP key |
300+
| POST | `/api/v1/agents/:name/rotate-key` | Session/API Key | Rotate OTLP key |
301+
| PATCH | `/api/v1/agents/:name` | Session/API Key | Rename agent |
284302
| GET | `/api/v1/security` | Session/API Key | Security score + events |
303+
| GET | `/api/v1/model-prices` | Session/API Key | Model pricing list |
304+
| GET/POST/PATCH/DELETE | `/api/v1/notifications` | Session/API Key | Notification rules CRUD |
305+
| GET/POST/DELETE | `/api/v1/notifications/email-provider` | Session/API Key | Email provider config |
306+
| GET/POST/PUT/DELETE | `/api/v1/routing/*` | Session/API Key | Routing config |
307+
| POST | `/api/v1/routing/resolve` | Bearer (mnfst_*) | Model resolution |
308+
| POST | `/v1/chat/completions` | Bearer (mnfst_*) | LLM proxy (OpenAI-compatible) |
309+
| GET | `/api/v1/events` | Session | SSE real-time events |
310+
| GET | `/api/v1/github/stars` | Public | GitHub star count |
285311
| POST | `/otlp/v1/traces` | Bearer (mnfst_*) | OTLP trace ingestion |
286312
| POST | `/otlp/v1/metrics` | Bearer (mnfst_*) | OTLP metric ingestion |
287313
| POST | `/otlp/v1/logs` | Bearer (mnfst_*) | OTLP log ingestion |
@@ -309,6 +335,9 @@ See `packages/backend/.env.example` for all variables. Key ones:
309335
- `DISCORD_CLIENT_ID` / `DISCORD_CLIENT_SECRET` — Discord OAuth (optional)
310336
- `PLUGIN_OTLP_ENDPOINT` — Custom OTLP endpoint for plugin setup UI.
311337
- `SEED_DATA` — Set `true` to seed demo data on startup.
338+
- `MANIFEST_MODE``local` or `cloud` (default: `cloud`). Switches between SQLite/loopback auth and PostgreSQL/Better Auth.
339+
- `MANIFEST_DB_PATH` — SQLite file path for local mode (default: in-memory).
340+
- `MANIFEST_TELEMETRY_OPTOUT` — Set `1` to disable anonymous product analytics.
312341

313342
## Domain Terminology
314343

@@ -331,6 +360,8 @@ To add a new font or icon library:
331360
3. Reference the local CSS in `index.html` (e.g. `<link href="/fonts/..." />`)
332361
4. Do **not** add external domains to the CSP directives
333362

363+
**Exception**: `connectSrc` includes `https://eu.i.posthog.com` for anonymous product analytics. This is the only external domain allowed. Opt-out via `MANIFEST_TELEMETRY_OPTOUT=1`.
364+
334365
## Architecture Notes
335366

336367
- **Single-service**: In production, `@nestjs/serve-static` serves `frontend/dist/` with SPA fallback. API routes (`/api/*`, `/otlp/*`) are excluded.
@@ -344,6 +375,10 @@ To add a new font or icon library:
344375
- **Validation**: Global `ValidationPipe` with `whitelist: true`, `forbidNonWhitelisted: true`. Explicit `@Type()` decorators on numeric DTO fields.
345376
- **OTLP auth caching**: `OtlpAuthGuard` caches valid API keys in-memory for 5 minutes to avoid repeated DB lookups.
346377
- **Database migrations**: TypeORM migrations are version-controlled in `src/database/migrations/`. `synchronize` is permanently `false`. Migrations auto-run on boot (`migrationsRun: true`) wrapped in a single transaction. The CLI DataSource is at `src/database/datasource.ts`. Better Auth manages its own tables separately via `ctx.runMigrations()`.
378+
- **Product analytics**: Anonymous usage tracking via PostHog (`eu.i.posthog.com`). Opt-out via `MANIFEST_TELEMETRY_OPTOUT=1`. Frontend: `services/analytics.ts`. Backend: `common/utils/product-telemetry.ts`.
379+
- **SSE**: `SseController` provides `/api/v1/events` for real-time dashboard updates.
380+
- **Notifications**: Cron-based threshold checking, supports Mailgun + Resend + SMTP email providers.
381+
- **LLM Routing**: Tier-based model routing with provider key management (AES-256-GCM encrypted) and OpenAI-compatible proxy at `/v1/chat/completions`.
347382

348383
## Releases & Changesets
349384

eslint.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default [
77
ignores: ['**/dist/**', '**/node_modules/**', '**/coverage/**', '**/*.js', '**/*.mjs'],
88
},
99
{
10-
files: ['packages/backend/src/**/*.ts', 'packages/frontend/src/**/*.ts', 'packages/frontend/src/**/*.tsx'],
10+
files: ['packages/backend/src/**/*.ts', 'packages/frontend/src/**/*.ts', 'packages/frontend/src/**/*.tsx', 'packages/openclaw-plugin/src/**/*.ts'],
1111
languageOptions: {
1212
parser: tsParser,
1313
parserOptions: {

0 commit comments

Comments
 (0)