Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .cursor/rules/00-core.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
description: Core context & output contract for AiM
globs:
- "**/*"
alwaysApply: true
---

# Core Project Context (AiM)
STACK: Next.js 15, React 19, TS, Prisma + Postgres, NextAuth, shadcn/ui, Zod.
DOMAINS: Organization, Campaign, Content, Asset, Schedule, AnalyticsEvent.

## OUTPUT CONTRACT (include in every response)
1) CHANGES — file list + brief diff
2) COMMANDS — install/migrate/dev/test
3) TESTS/RESULTS — build/typecheck/lint/health logs
4) GIT — branch name, commit SHAs, PR link (if cloud)

MUST READ (if present): docs/SPEC.md, docs/data-model.md, docs/api/*.md
DO NOT:
- Touch real `.env`; only update `.env.example`
- Add dependencies without explicit approval
22 changes: 22 additions & 0 deletions .cursor/rules/01-guardrails.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
description: Guardrails — permissions, limits, safety
globs:
- "app/**"
- "features/**"
- "prisma/**"
- "app/api/**"
- "lib/**"
alwaysApply: false
---

# Guardrails
WRITE ALLOWED: app/**, features/**, lib/**, prisma/**, app/api/**
ASK FIRST: package.json, pnpm-lock.yaml, next.config.ts, .github/workflows/**

SECURITY:
- Mọi route phải check session + RBAC
- Validate input bằng Zod; trả JSON { ok, data | error }

LIMITS:
- ≤ 20 files / ≤ 800 lines diff / PR; vượt ngưỡng → dừng và hỏi
- Không ghi logs nhạy cảm (PII)
16 changes: 16 additions & 0 deletions .cursor/rules/02-repo-map.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
description: Repo map & module boundaries for AiM
globs:
- "**/*"
alwaysApply: false
---

# Repo Map & Boundaries
FEATURES: features/{auth,orgs,campaigns,content,assets,calendar,analytics,settings}
API: app/api/[orgId]/{campaigns,content,assets,schedules,analytics}/...
DATA: prisma/schema.prisma (source of truth)
UI: components/layout/*, components/ui/*, components/dashboards/*

RULE:
- Tôn trọng boundaries: service/repo/UI tách lớp
- Không gọi Prisma trực tiếp từ UI client
20 changes: 20 additions & 0 deletions .cursor/rules/03-sop-ai-sse.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
description: SOP for AI-SSE — how to deliver a PR
globs:
- "docs/tasks/**"
- "app/**"
- "features/**"
- "app/api/**"
- "prisma/**"
alwaysApply: false
---

# SOP for AI-SSE (per PR)
ACCEPTANCE (check all):
- Feature chạy sau khi `pnpm dev`
- Inputs validated (Zod); Auth + RBAC: 401/403 đúng chỗ
- Có migration + seed + rollback note (dev)
- CI pass (build, typecheck, lint, /api/health)

RESPONSE FORMAT = theo OUTPUT CONTRACT.
Nếu chạm schema/kiến trúc → tạo docs/adr/####-*.md
16 changes: 16 additions & 0 deletions .cursor/rules/04-api-style.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
description: API style & contracts for route handlers
globs:
- "app/api/**"
- "lib/**"
alwaysApply: false
---

# API Style (Next.js Route Handlers)
RESPONSE SHAPE:
{ "ok": true, "data": ... } | { "ok": false, "error": { "code", "message", "details?" } }

VALIDATION: Zod per route → 400 invalid; 404 not found.
ORG SCOPING: Lấy orgId từ path; cấm cross-org access.
PAGINATION: ?page=&limit= → { items, total, page, limit }
ERRORS: Dùng mã ngắn (e.g., E_VALIDATION, E_FORBIDDEN)
17 changes: 17 additions & 0 deletions .cursor/rules/05-rbac-security.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
description: RBAC roles & security checklist
globs:
- "app/api/**"
- "lib/**"
- "middleware.ts"
alwaysApply: false
---

# RBAC & Security
ROLES: ADMIN, BRAND_OWNER, CREATOR (mặc định deny-by-default).
HELPERS: lib/rbac.ts — kiểm tra quyền theo orgId + vai trò.

CHECKLIST:
- [ ] Session bắt buộc cho routes không public
- [ ] Sanitize input/output; strip secrets khỏi logs
- [ ] Rate limit (nếu có hành vi ghi/nhạy cảm)
18 changes: 18 additions & 0 deletions .cursor/rules/06-ci-quality.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
description: CI pipeline & quality gates
globs:
- ".github/workflows/**"
- "**/*"
alwaysApply: false
---

# CI & Quality Gates
CI MUST:
- build, typecheck, lint
- curl /api/health trả 200

PR CHECKLIST (đi vào PR template):
- [ ] Zod validation
- [ ] Auth + RBAC checks
- [ ] Migration/seed + rollback note
- [ ] CI xanh
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Database (Postgres)
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/circle_dev?schema=public"

# NextAuth
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="changeme-in-local"

# Dev-only credentials login
DEV_LOGIN_PASSWORD="dev"

49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: CI

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Lint
run: pnpm run lint

- name: Typecheck
run: pnpm run typecheck

- name: Run unit tests
run: pnpm run test

- name: Build
run: pnpm run build

- name: Install Playwright browsers
run: npx playwright install --with-deps

- name: Run E2E tests
run: pnpm run test:e2e

- name: Health check
run: |
pnpm run start &
sleep 10
curl -f http://localhost:3000/api/health || exit 1
pkill -f "next start" || true
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*
.env
.env.local
.env.production
# .env.example is allowed to be committed

# vercel
.vercel
Expand Down
1 change: 1 addition & 0 deletions .obsidian/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions .obsidian/appearance.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
33 changes: 33 additions & 0 deletions .obsidian/core-plugins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"file-explorer": true,
"global-search": true,
"switcher": true,
"graph": true,
"backlink": true,
"canvas": true,
"outgoing-link": true,
"tag-pane": true,
"footnotes": false,
"properties": false,
"page-preview": true,
"daily-notes": true,
"templates": true,
"note-composer": true,
"command-palette": true,
"slash-command": false,
"editor-status": true,
"bookmarks": true,
"markdown-importer": false,
"zk-prefixer": false,
"random-note": false,
"outline": true,
"word-count": true,
"slides": false,
"audio-recorder": false,
"workspaces": false,
"file-recovery": true,
"publish": false,
"sync": true,
"bases": true,
"webviewer": false
}
Loading