level-up-mcp-server-cn 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/projects/c--Users-klexi-OneDrive-Desktop-Levelup-level-up-mcp-server/memory/project_testing_service.md +11 -0
- package/.claude/settings.local.json +10 -0
- package/.env.example +19 -0
- package/CLAUDE.md +222 -0
- package/CODE_REVIEW.md +282 -0
- package/LICENSE +64 -0
- package/README.md +198 -0
- package/dist/constants.d.ts +33 -0
- package/dist/constants.js +78 -0
- package/dist/constants.js.map +1 -0
- package/dist/data/quest-seeds.d.ts +18 -0
- package/dist/data/quest-seeds.js +380 -0
- package/dist/data/quest-seeds.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +260 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/common.d.ts +33 -0
- package/dist/schemas/common.js +96 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/services/dispatcher.d.ts +27 -0
- package/dist/services/dispatcher.js +47 -0
- package/dist/services/dispatcher.js.map +1 -0
- package/dist/services/errors.d.ts +56 -0
- package/dist/services/errors.js +99 -0
- package/dist/services/errors.js.map +1 -0
- package/dist/services/format.d.ts +74 -0
- package/dist/services/format.js +144 -0
- package/dist/services/format.js.map +1 -0
- package/dist/services/ownership.d.ts +19 -0
- package/dist/services/ownership.js +79 -0
- package/dist/services/ownership.js.map +1 -0
- package/dist/services/quality-gate.d.ts +45 -0
- package/dist/services/quality-gate.js +131 -0
- package/dist/services/quality-gate.js.map +1 -0
- package/dist/services/rate-limit.d.ts +12 -0
- package/dist/services/rate-limit.js +49 -0
- package/dist/services/rate-limit.js.map +1 -0
- package/dist/services/register.d.ts +49 -0
- package/dist/services/register.js +63 -0
- package/dist/services/register.js.map +1 -0
- package/dist/services/supabase.d.ts +10 -0
- package/dist/services/supabase.js +79 -0
- package/dist/services/supabase.js.map +1 -0
- package/dist/tools/achievements.d.ts +6 -0
- package/dist/tools/achievements.js +242 -0
- package/dist/tools/achievements.js.map +1 -0
- package/dist/tools/admin.d.ts +16 -0
- package/dist/tools/admin.js +328 -0
- package/dist/tools/admin.js.map +1 -0
- package/dist/tools/agents.d.ts +3 -0
- package/dist/tools/agents.js +400 -0
- package/dist/tools/agents.js.map +1 -0
- package/dist/tools/bootstrap.d.ts +17 -0
- package/dist/tools/bootstrap.js +565 -0
- package/dist/tools/bootstrap.js.map +1 -0
- package/dist/tools/dispatchers/admin.d.ts +3 -0
- package/dist/tools/dispatchers/admin.js +50 -0
- package/dist/tools/dispatchers/admin.js.map +1 -0
- package/dist/tools/dispatchers/eval.d.ts +3 -0
- package/dist/tools/dispatchers/eval.js +40 -0
- package/dist/tools/dispatchers/eval.js.map +1 -0
- package/dist/tools/dispatchers/quests.d.ts +3 -0
- package/dist/tools/dispatchers/quests.js +60 -0
- package/dist/tools/dispatchers/quests.js.map +1 -0
- package/dist/tools/dispatchers/session.d.ts +3 -0
- package/dist/tools/dispatchers/session.js +38 -0
- package/dist/tools/dispatchers/session.js.map +1 -0
- package/dist/tools/dispatchers/skills.d.ts +3 -0
- package/dist/tools/dispatchers/skills.js +49 -0
- package/dist/tools/dispatchers/skills.js.map +1 -0
- package/dist/tools/dispatchers/tasks.d.ts +3 -0
- package/dist/tools/dispatchers/tasks.js +53 -0
- package/dist/tools/dispatchers/tasks.js.map +1 -0
- package/dist/tools/dispatchers/users.d.ts +3 -0
- package/dist/tools/dispatchers/users.js +65 -0
- package/dist/tools/dispatchers/users.js.map +1 -0
- package/dist/tools/dispatchers/xp.d.ts +3 -0
- package/dist/tools/dispatchers/xp.js +51 -0
- package/dist/tools/dispatchers/xp.js.map +1 -0
- package/dist/tools/growth-plan.d.ts +5 -0
- package/dist/tools/growth-plan.js +791 -0
- package/dist/tools/growth-plan.js.map +1 -0
- package/dist/tools/leaderboards.d.ts +10 -0
- package/dist/tools/leaderboards.js +279 -0
- package/dist/tools/leaderboards.js.map +1 -0
- package/dist/tools/leveling.d.ts +24 -0
- package/dist/tools/leveling.js +356 -0
- package/dist/tools/leveling.js.map +1 -0
- package/dist/tools/metrics.d.ts +3 -0
- package/dist/tools/metrics.js +247 -0
- package/dist/tools/metrics.js.map +1 -0
- package/dist/tools/quests.d.ts +5 -0
- package/dist/tools/quests.js +586 -0
- package/dist/tools/quests.js.map +1 -0
- package/dist/tools/ratings.d.ts +11 -0
- package/dist/tools/ratings.js +564 -0
- package/dist/tools/ratings.js.map +1 -0
- package/dist/tools/skills.d.ts +66 -0
- package/dist/tools/skills.js +1112 -0
- package/dist/tools/skills.js.map +1 -0
- package/dist/tools/system.d.ts +31 -0
- package/dist/tools/system.js +605 -0
- package/dist/tools/system.js.map +1 -0
- package/dist/tools/tasks.d.ts +73 -0
- package/dist/tools/tasks.js +1572 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/users.d.ts +97 -0
- package/dist/tools/users.js +1306 -0
- package/dist/tools/users.js.map +1 -0
- package/dist/tools/xp.d.ts +38 -0
- package/dist/tools/xp.js +670 -0
- package/dist/tools/xp.js.map +1 -0
- package/dist/types.d.ts +178 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/docs/recommended-skillsets.md +622 -0
- package/docs/skills-and-abilities-review.md +672 -0
- package/docs/v0.3-roadmap.md +191 -0
- package/package.json +35 -0
- package/sql/agent_pending_installs.sql +28 -0
- package/sql/award_class_xp.sql +81 -0
- package/supabase/.temp/cli-latest +1 -0
- package/supabase/.temp/gotrue-version +1 -0
- package/supabase/.temp/pooler-url +1 -0
- package/supabase/.temp/postgres-version +1 -0
- package/supabase/.temp/project-ref +1 -0
- package/supabase/.temp/rest-version +1 -0
- package/supabase/.temp/storage-migration +1 -0
- package/supabase/.temp/storage-version +1 -0
- package/supabase/migrations/20260314000000_anon_rls_policies.sql +311 -0
- package/supabase/migrations/20260314000001_ownership_rpcs.sql +382 -0
- package/supabase/migrations/20260314000002_evidence_and_growth_plan.sql +97 -0
- package/supabase/migrations/20260317000000_seed_quests.sql +62 -0
- package/supabase/migrations/20260317000001_star_cooldown_and_fixes.sql +16 -0
- package/supabase/migrations/20260318000000_restore_rank_names.sql +25 -0
- package/supabase/migrations/20260320000000_chinese_rank_names.sql +24 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# v0.3 Roadmap
|
|
2
|
+
|
|
3
|
+
## Release Theme: Bootstrap, Quests & UX
|
|
4
|
+
|
|
5
|
+
Target: After v0.2.x feedback incorporated
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## v0.2.x Review Summary (2026-03-17)
|
|
10
|
+
|
|
11
|
+
Two reviews received — Claude (technical) and OpenClaw/Maine (user testing on Ken's account).
|
|
12
|
+
|
|
13
|
+
**Key findings:**
|
|
14
|
+
- User XP too low (2-6 XP per task due to 60/40 agent split) — users feel unrewarded
|
|
15
|
+
- Class tracks (Trainer/Orchestrator/Partner) completely unused — 0 XP across all users
|
|
16
|
+
- Output type rarely set (90% null), evidence rarely attached
|
|
17
|
+
- Orphaned tasks — 2 tasks stuck in_progress with no recovery mechanism
|
|
18
|
+
- No onboarding guidance — users don't know what to do next
|
|
19
|
+
- 15+ tool calls needed for full onboarding — too much friction
|
|
20
|
+
- Rating: 6/10 — good foundation, needs better UX
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## v0.3 Build Order (by impact × feasibility)
|
|
25
|
+
|
|
26
|
+
### Phase 1: CRITICAL — Unblock adoption
|
|
27
|
+
|
|
28
|
+
#### 1. Session Bootstrap (`levelup_bootstrap`)
|
|
29
|
+
Single tool call returns complete session state for stateless agents.
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
levelup_bootstrap(user_id?, agent_id?, platform?)
|
|
33
|
+
→ Returns: user profile, agent profile, orphaned tasks, recent tasks,
|
|
34
|
+
active quests, coaching nudge, recovery actions
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Solves:** 3 sequential tool calls → 1. Orphaned task recovery. Works across fresh chats.
|
|
38
|
+
|
|
39
|
+
#### 2. Setup Wizard (`levelup_setup_wizard`)
|
|
40
|
+
One-call onboarding that auto-maps installed MCPs to skills.
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
levelup_setup_wizard(agent_id, installed_mcps?: string[], auto_register_skills?: true)
|
|
44
|
+
→ Returns: skills_registered, skills_already_had, suggested_mcps, suggested_skills
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Solves:** 15+ tool calls → 1 for skill registration. MCP-to-skill lookup table built in.
|
|
48
|
+
|
|
49
|
+
#### 3. Quest / Challenge System
|
|
50
|
+
Directed learning through onboarding, skill, and weekly quests.
|
|
51
|
+
|
|
52
|
+
**Onboarding quests:** "Register profile" → "Add 3 skills" → "Complete first task" → "Install 3 MCPs" → "Quality score > 3.5"
|
|
53
|
+
**Skill quests:** "Use GitHub MCP to create a PR" → "Set up automated workflow with 2+ MCPs"
|
|
54
|
+
**Weekly challenges:** "Complete 5 tasks" → "Increase skill proficiency" → "5-day streak"
|
|
55
|
+
|
|
56
|
+
Tools: `levelup_get_active_quests`, `levelup_start_quest`, `levelup_check_quest_progress`
|
|
57
|
+
Note: 12 quest tools already exist in quests.ts but are not active.
|
|
58
|
+
|
|
59
|
+
### Phase 2: HIGH — Drive engagement
|
|
60
|
+
|
|
61
|
+
#### 4. Fix Growth Plan Quality
|
|
62
|
+
- Deduplicate MCP install suggestions (group skills-per-MCP)
|
|
63
|
+
- Mix action types — max 3 installs before suggesting a task
|
|
64
|
+
- Filter by already-installed MCPs
|
|
65
|
+
- Differentiate priorities (critical/recommended/optional)
|
|
66
|
+
- Respect 3/day install cooldown — spread across days
|
|
67
|
+
|
|
68
|
+
#### 5. Contextual Coaching (`levelup_get_coaching_suggestions`)
|
|
69
|
+
Analyzes task history, tool usage, automation ratio, skill gaps, unused MCPs.
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
levelup_get_coaching_suggestions(user_id, agent_id?, focus?)
|
|
73
|
+
→ Returns: suggestions with evidence, impact, pre-filled action params
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Example: "You've done 8 email drafts manually. Gmail MCP is installed but unused in tasks."
|
|
77
|
+
|
|
78
|
+
#### 6. Workflow Templates (`levelup_browse_workflows`)
|
|
79
|
+
Multi-step recipes using multiple MCPs. Shows which MCPs user has vs needs.
|
|
80
|
+
|
|
81
|
+
Seed workflows: Bug fix pipeline, Feature sprint, Blog post pipeline, Meeting automation, etc.
|
|
82
|
+
|
|
83
|
+
### Phase 3: MEDIUM — Polish & consolidate
|
|
84
|
+
|
|
85
|
+
#### 7. Consolidated Dashboard (`levelup_dashboard`)
|
|
86
|
+
One tool replaces 6+: user profile + progress + achievements + recap + agents + quests.
|
|
87
|
+
|
|
88
|
+
#### 8. Idempotent Task Tracking (`levelup_resume_or_start`)
|
|
89
|
+
Checks for in-progress task with similar title before creating new one. Auto-fail tasks orphaned 24h+.
|
|
90
|
+
|
|
91
|
+
#### 9. Progressive Tool Disclosure
|
|
92
|
+
Level 1-3: ~15 tools (basics). Level 4-7: +12 tools (intermediate). Level 8+: all tools (admin/power).
|
|
93
|
+
|
|
94
|
+
#### 10. Achievement System Seeding
|
|
95
|
+
Seed 30-50 achievements: First Steps, Century (100 XP), Rank Up, On a Roll (3-day streak), Craftsman (4.5+ quality), Night Owl, Speed Demon, Polyglot.
|
|
96
|
+
|
|
97
|
+
### Phase 4: LOW — Future infrastructure
|
|
98
|
+
|
|
99
|
+
#### 11. Webhook / Push Notifications
|
|
100
|
+
Platforms subscribe to events: level_up, achievement_earned, quest_available, weekly_recap.
|
|
101
|
+
|
|
102
|
+
#### 12. Testing Service (separate repo: level-up-test-service)
|
|
103
|
+
See testing service architecture below.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## User XP Balance Fix
|
|
108
|
+
|
|
109
|
+
**Problem:** Users get 40% of XP in user_with_agent tasks (60% to agent). Users earn 2-6 XP per task, feels unrewarding.
|
|
110
|
+
|
|
111
|
+
**Options:**
|
|
112
|
+
- A) Adjust default split to 50/50
|
|
113
|
+
- B) Add user-only XP bonuses (evidence bonus, streak bonus, quest completion)
|
|
114
|
+
- C) Both — rebalance split AND add user bonuses
|
|
115
|
+
- D) Keep split but add class track XP (Trainer/Orchestrator/Partner earn separately)
|
|
116
|
+
|
|
117
|
+
**Decision needed before v0.3.**
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Feature: Testing Service (deferred to v0.4+)
|
|
122
|
+
|
|
123
|
+
### Architecture
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
Agent <-> Level-Up MCP <-> Testing Service (HTTP API)
|
|
127
|
+
|
|
|
128
|
+
Supabase DB
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Test Types
|
|
132
|
+
|
|
133
|
+
| Type | Trigger | Purpose |
|
|
134
|
+
|------|---------|---------|
|
|
135
|
+
| Skill verification | Agent claims skill proficiency | Prove agent can actually use a skill |
|
|
136
|
+
| Rank advancement | Agent at level 10 (D) -> 11 (C) | Gate or bonus for rank-up milestones |
|
|
137
|
+
| Periodic re-test | Configurable interval | Prevent skill decay / stale claims |
|
|
138
|
+
|
|
139
|
+
### Open Design Questions
|
|
140
|
+
|
|
141
|
+
1. Gated vs optional — Must agents test to rank up, or just bonus XP?
|
|
142
|
+
2. Evaluation method — LLM judge vs rubric checklist vs hybrid
|
|
143
|
+
3. Challenge source — Fixed bank vs LLM-generated per attempt
|
|
144
|
+
4. Cheating prevention — Time limits, unique challenges, cooldown, max attempts
|
|
145
|
+
5. Deployment — Separate Railway service vs serverless
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Other Ideas (backlog)
|
|
150
|
+
|
|
151
|
+
- [ ] MCP discovery tool — search Docker MCP registry / awesome-mcp-servers
|
|
152
|
+
- [ ] Allow agents to install any MCP and map to closest ability category
|
|
153
|
+
- [ ] Frontend experiment using Google Flow
|
|
154
|
+
- [ ] Testing module experiment using Mirro (simulated AI reviewers)
|
|
155
|
+
- [ ] `npx level-up-mcp-server --setup` auto-config command
|
|
156
|
+
- [ ] Blockchain integration — on-chain XP/achievement verification, portable agent credentials
|
|
157
|
+
- [ ] Class track activation (Trainer/Orchestrator/Partner)
|
|
158
|
+
- [ ] User preference snippet generator for persistent identity
|
|
159
|
+
- [ ] MCP-level session identity (requires MCP spec changes)
|
|
160
|
+
- [ ] Auto-prompt users after tasks for output_type and evidence
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Completed (v0.2.x)
|
|
165
|
+
|
|
166
|
+
- [x] Agents not earning XP — fixed agent_id flow (v0.2.2)
|
|
167
|
+
- [x] Stars displayed in rank responses (v0.2.2)
|
|
168
|
+
- [x] register_user/register_agent → RPC with fallback (v0.2.4)
|
|
169
|
+
- [x] Achievement auto-triggers (v0.2.2)
|
|
170
|
+
- [x] Skill discount passed to level-up RPC (v0.2.2)
|
|
171
|
+
- [x] Tool installation XP +20 (v0.2.2)
|
|
172
|
+
- [x] Whoami auto-detection (v0.2.5)
|
|
173
|
+
- [x] Growth plan level-gating (v0.2.5)
|
|
174
|
+
- [x] Evidence requirements per tier (v0.2.4)
|
|
175
|
+
- [x] Browse skillsets — 18 categories (v0.2.4)
|
|
176
|
+
- [x] check_level_up RPC fix (v0.2.6)
|
|
177
|
+
- [x] Evidence sanitization pipeline (v0.2.1)
|
|
178
|
+
- [x] Tier override + auto-downgrade (v0.2.1)
|
|
179
|
+
- [x] Anti-gaming: quality gate, rate limiting, duration floors (v0.2.0)
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Versioning Plan
|
|
184
|
+
|
|
185
|
+
| Version | Scope |
|
|
186
|
+
|---------|-------|
|
|
187
|
+
| 0.2.0-0.2.6 | Foundation — anti-gaming, evidence, growth plans, whoami, skillsets |
|
|
188
|
+
| 0.3.0 | Bootstrap + setup wizard + quest system + growth plan fixes |
|
|
189
|
+
| 0.3.x | Coaching, workflows, dashboard consolidation, achievements |
|
|
190
|
+
| 0.4.0 | Testing service + progressive disclosure + webhooks |
|
|
191
|
+
| 1.0.0 | Blockchain integration + stable API |
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "level-up-mcp-server-cn",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Level-Up 游戏化MCP服务器 — 为人类和AI智能体追踪经验值、等级、技能和任务",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"level-up-mcp-server-cn": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"start:http": "TRANSPORT=http node dist/index.js",
|
|
15
|
+
"pretest": "rm -rf node_modules/.vite node_modules/.experimental-vitest-cache",
|
|
16
|
+
"test": "vitest run --pool forks",
|
|
17
|
+
"test:watch": "vitest"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
21
|
+
"@supabase/supabase-js": "^2.49.0",
|
|
22
|
+
"express": "^5.0.1",
|
|
23
|
+
"zod": "^3.25.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/express": "^5.0.0",
|
|
27
|
+
"@types/node": "^22.0.0",
|
|
28
|
+
"typescript": "^5.7.0",
|
|
29
|
+
"vitest": "^4.1.0"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.0.0"
|
|
33
|
+
},
|
|
34
|
+
"license": "BUSL-1.1"
|
|
35
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-- agent_pending_installs: tracks frontend install requests before agent confirmation
|
|
2
|
+
-- Flow: frontend INSERT (pending) → agent reads → agent installs → agent UPDATE (confirmed)
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS agent_pending_installs (
|
|
5
|
+
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
6
|
+
agent_id uuid NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
7
|
+
item_type text NOT NULL CHECK (item_type IN ('mcp', 'skill')),
|
|
8
|
+
item_name text NOT NULL,
|
|
9
|
+
status text NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'confirmed', 'cancelled')),
|
|
10
|
+
created_at timestamptz DEFAULT now(),
|
|
11
|
+
confirmed_at timestamptz
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
-- Index for fast lookup by agent
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_pending_installs_agent
|
|
16
|
+
ON agent_pending_installs(agent_id, status);
|
|
17
|
+
|
|
18
|
+
-- RLS: allow anon read/write for now (frontend uses anon key)
|
|
19
|
+
ALTER TABLE agent_pending_installs ENABLE ROW LEVEL SECURITY;
|
|
20
|
+
|
|
21
|
+
CREATE POLICY "anon_read_pending_installs" ON agent_pending_installs
|
|
22
|
+
FOR SELECT TO anon USING (true);
|
|
23
|
+
|
|
24
|
+
CREATE POLICY "anon_insert_pending_installs" ON agent_pending_installs
|
|
25
|
+
FOR INSERT TO anon WITH CHECK (true);
|
|
26
|
+
|
|
27
|
+
CREATE POLICY "anon_update_pending_installs" ON agent_pending_installs
|
|
28
|
+
FOR UPDATE TO anon USING (true) WITH CHECK (true);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
-- ============================================================
|
|
2
|
+
-- RPC: award_class_xp
|
|
3
|
+
-- Awards class XP to a user's class track (trainer/partner/orchestrator).
|
|
4
|
+
-- Updates user_class_progress and records the XP in xp_ledger
|
|
5
|
+
-- with the class name as xp_type.
|
|
6
|
+
-- ============================================================
|
|
7
|
+
CREATE OR REPLACE FUNCTION award_class_xp(
|
|
8
|
+
p_user_id UUID,
|
|
9
|
+
p_class_name TEXT,
|
|
10
|
+
p_amount INTEGER,
|
|
11
|
+
p_source_type TEXT,
|
|
12
|
+
p_description TEXT,
|
|
13
|
+
p_source_id UUID DEFAULT NULL
|
|
14
|
+
) RETURNS JSONB AS $$
|
|
15
|
+
DECLARE
|
|
16
|
+
v_class_row RECORD;
|
|
17
|
+
v_running_total BIGINT;
|
|
18
|
+
BEGIN
|
|
19
|
+
-- Validate user exists
|
|
20
|
+
IF NOT EXISTS (SELECT 1 FROM users WHERE id = p_user_id) THEN
|
|
21
|
+
RETURN jsonb_build_object('success', false, 'error', 'User not found');
|
|
22
|
+
END IF;
|
|
23
|
+
|
|
24
|
+
-- Validate class name
|
|
25
|
+
IF p_class_name NOT IN ('trainer', 'partner', 'orchestrator') THEN
|
|
26
|
+
RETURN jsonb_build_object('success', false, 'error', 'Invalid class_name');
|
|
27
|
+
END IF;
|
|
28
|
+
|
|
29
|
+
-- Validate amount is positive
|
|
30
|
+
IF p_amount <= 0 THEN
|
|
31
|
+
RETURN jsonb_build_object('success', false, 'error', 'Amount must be positive');
|
|
32
|
+
END IF;
|
|
33
|
+
|
|
34
|
+
-- Get the class progress row
|
|
35
|
+
SELECT id, class_xp INTO v_class_row
|
|
36
|
+
FROM user_class_progress
|
|
37
|
+
WHERE user_id = p_user_id AND class_name = p_class_name;
|
|
38
|
+
|
|
39
|
+
IF NOT FOUND THEN
|
|
40
|
+
RETURN jsonb_build_object('success', false, 'error', 'Class progress row not found');
|
|
41
|
+
END IF;
|
|
42
|
+
|
|
43
|
+
-- Update class XP
|
|
44
|
+
UPDATE user_class_progress
|
|
45
|
+
SET class_xp = v_class_row.class_xp + p_amount
|
|
46
|
+
WHERE id = v_class_row.id;
|
|
47
|
+
|
|
48
|
+
-- Get running total for xp_ledger
|
|
49
|
+
SELECT COALESCE(running_total, 0) INTO v_running_total
|
|
50
|
+
FROM xp_ledger
|
|
51
|
+
WHERE entity_type = 'user' AND entity_id = p_user_id
|
|
52
|
+
ORDER BY created_at DESC
|
|
53
|
+
LIMIT 1;
|
|
54
|
+
|
|
55
|
+
IF NOT FOUND THEN
|
|
56
|
+
v_running_total := 0;
|
|
57
|
+
END IF;
|
|
58
|
+
|
|
59
|
+
-- Note: class XP is tracked separately; running_total here is for audit trail only
|
|
60
|
+
-- and does NOT get added to main_xp (class XP is a parallel track)
|
|
61
|
+
|
|
62
|
+
-- Insert ledger entry with class name as xp_type
|
|
63
|
+
INSERT INTO xp_ledger (
|
|
64
|
+
entity_type, entity_id, xp_type, amount,
|
|
65
|
+
source_type, source_id, description, running_total
|
|
66
|
+
) VALUES (
|
|
67
|
+
'user', p_user_id, p_class_name, p_amount,
|
|
68
|
+
p_source_type, p_source_id, p_description, v_running_total
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
RETURN jsonb_build_object(
|
|
72
|
+
'success', true,
|
|
73
|
+
'class_name', p_class_name,
|
|
74
|
+
'new_class_xp', v_class_row.class_xp + p_amount,
|
|
75
|
+
'amount', p_amount
|
|
76
|
+
);
|
|
77
|
+
END;
|
|
78
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
79
|
+
|
|
80
|
+
-- Grant access to anon role
|
|
81
|
+
GRANT EXECUTE ON FUNCTION award_class_xp(UUID, TEXT, INTEGER, TEXT, TEXT, UUID) TO anon;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v2.78.1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v2.187.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
postgresql://postgres.pxanrmpwptinbtwigqdt@aws-1-ap-southeast-1.pooler.supabase.com:5432/postgres
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
17.6.1.084
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pxanrmpwptinbtwigqdt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v14.4
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fix-optimized-search-function
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v1.37.7
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
-- ============================================================
|
|
2
|
+
-- Migration: Add anon role RLS policies for MCP server
|
|
3
|
+
-- ============================================================
|
|
4
|
+
-- The MCP server connects with the anon key (no auth.uid()).
|
|
5
|
+
-- These policies allow the MCP tools to perform core operations
|
|
6
|
+
-- while keeping XP/level columns locked to SECURITY DEFINER RPCs.
|
|
7
|
+
--
|
|
8
|
+
-- EXISTING anon policies (already in place, DO NOT re-create):
|
|
9
|
+
-- anon SELECT on: users, user_identities, user_class_progress,
|
|
10
|
+
-- user_achievements, user_level_requirements, agents, agent_skills,
|
|
11
|
+
-- agent_tool_installations, agent_skill_snapshots, agent_transfers,
|
|
12
|
+
-- agent_integrity_log, agent_cross_ratings, skills, tasks,
|
|
13
|
+
-- weekly_bonus_criteria, achievement_definitions, verification_rules,
|
|
14
|
+
-- + all reference tables (level_curves, rank_definitions, xp_config, etc.)
|
|
15
|
+
-- anon INSERT on: user_identities, agent_skills, agent_skill_snapshots,
|
|
16
|
+
-- agent_transfers, agent_integrity_log, agent_cross_ratings, skills,
|
|
17
|
+
-- agent_tool_installations, user_level_requirements
|
|
18
|
+
-- anon UPDATE on: user_identities, user_level_requirements, agent_skills
|
|
19
|
+
--
|
|
20
|
+
-- STRATEGY:
|
|
21
|
+
-- - XP/level writes → only via SECURITY DEFINER RPCs (locked)
|
|
22
|
+
-- - Task/agent/user creation → anon INSERT allowed (MCP tools enforce rules)
|
|
23
|
+
-- - Config/rule tables → read-only for anon (admin via service_role)
|
|
24
|
+
-- ============================================================
|
|
25
|
+
|
|
26
|
+
-- ============================================================
|
|
27
|
+
-- 1. USERS: Allow registration and safe profile updates
|
|
28
|
+
-- ============================================================
|
|
29
|
+
|
|
30
|
+
-- Anon can register new users
|
|
31
|
+
CREATE POLICY "anon_insert_users" ON users
|
|
32
|
+
FOR INSERT TO anon
|
|
33
|
+
WITH CHECK (true);
|
|
34
|
+
|
|
35
|
+
-- NO anon UPDATE on users — all updates go through RPCs:
|
|
36
|
+
-- update_user_profile() for safe fields
|
|
37
|
+
-- merge_user_profiles() for profile merges
|
|
38
|
+
-- award_task_xp() for XP (existing)
|
|
39
|
+
-- check_and_apply_level_up() for levels (existing)
|
|
40
|
+
|
|
41
|
+
-- ============================================================
|
|
42
|
+
-- 2. USER_CLASS_PROGRESS: Allow creation during registration
|
|
43
|
+
-- ============================================================
|
|
44
|
+
|
|
45
|
+
CREATE POLICY "anon_insert_user_class_progress" ON user_class_progress
|
|
46
|
+
FOR INSERT TO anon
|
|
47
|
+
WITH CHECK (true);
|
|
48
|
+
|
|
49
|
+
-- NO anon UPDATE on user_class_progress — updates via RPCs only
|
|
50
|
+
|
|
51
|
+
-- ============================================================
|
|
52
|
+
-- 3. AGENTS: Allow registration, safe updates only
|
|
53
|
+
-- ============================================================
|
|
54
|
+
|
|
55
|
+
-- Anon can register agents
|
|
56
|
+
CREATE POLICY "anon_insert_agents" ON agents
|
|
57
|
+
FOR INSERT TO anon
|
|
58
|
+
WITH CHECK (true);
|
|
59
|
+
|
|
60
|
+
-- NO anon UPDATE on agents — all updates go through RPCs:
|
|
61
|
+
-- update_agent_profile() for safe fields (with ownership check)
|
|
62
|
+
-- update_integrity_score() for integrity
|
|
63
|
+
-- record_level_up_timestamp() for level-up timestamps
|
|
64
|
+
-- award_task_xp() for XP (existing)
|
|
65
|
+
-- check_and_apply_level_up() for levels (existing)
|
|
66
|
+
|
|
67
|
+
-- ============================================================
|
|
68
|
+
-- 4. TASKS: Allow create and update (MCP enforces min duration,
|
|
69
|
+
-- rate limits, cooldowns)
|
|
70
|
+
-- ============================================================
|
|
71
|
+
|
|
72
|
+
CREATE POLICY "anon_insert_tasks" ON tasks
|
|
73
|
+
FOR INSERT TO anon
|
|
74
|
+
WITH CHECK (
|
|
75
|
+
status = 'in_progress' -- Can only create tasks as in_progress
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
-- NO anon UPDATE on tasks — all updates go through update_task_status() RPC
|
|
79
|
+
-- which verifies the caller owns the task
|
|
80
|
+
|
|
81
|
+
-- ============================================================
|
|
82
|
+
-- 5. TASK SUPPORT TABLES: Ratings, expectations, evaluations, TDI
|
|
83
|
+
-- ============================================================
|
|
84
|
+
|
|
85
|
+
CREATE POLICY "anon_insert_task_ratings" ON task_ratings
|
|
86
|
+
FOR INSERT TO anon
|
|
87
|
+
WITH CHECK (true);
|
|
88
|
+
|
|
89
|
+
CREATE POLICY "anon_insert_task_expectations" ON task_expectations
|
|
90
|
+
FOR INSERT TO anon
|
|
91
|
+
WITH CHECK (true);
|
|
92
|
+
|
|
93
|
+
CREATE POLICY "anon_read_task_evaluations" ON task_evaluations
|
|
94
|
+
FOR SELECT TO anon
|
|
95
|
+
USING (true);
|
|
96
|
+
|
|
97
|
+
CREATE POLICY "anon_insert_task_evaluations" ON task_evaluations
|
|
98
|
+
FOR INSERT TO anon
|
|
99
|
+
WITH CHECK (true);
|
|
100
|
+
|
|
101
|
+
CREATE POLICY "anon_read_task_milestones" ON task_milestones
|
|
102
|
+
FOR SELECT TO anon
|
|
103
|
+
USING (true);
|
|
104
|
+
|
|
105
|
+
CREATE POLICY "anon_insert_task_milestones" ON task_milestones
|
|
106
|
+
FOR INSERT TO anon
|
|
107
|
+
WITH CHECK (true);
|
|
108
|
+
|
|
109
|
+
CREATE POLICY "anon_update_task_milestones" ON task_milestones
|
|
110
|
+
FOR UPDATE TO anon
|
|
111
|
+
USING (true)
|
|
112
|
+
WITH CHECK (true);
|
|
113
|
+
|
|
114
|
+
-- TDI: Allow MCP to upsert difficulty index entries
|
|
115
|
+
CREATE POLICY "anon_insert_task_difficulty_index" ON task_difficulty_index
|
|
116
|
+
FOR INSERT TO anon
|
|
117
|
+
WITH CHECK (true);
|
|
118
|
+
|
|
119
|
+
CREATE POLICY "anon_update_task_difficulty_index" ON task_difficulty_index
|
|
120
|
+
FOR UPDATE TO anon
|
|
121
|
+
USING (true)
|
|
122
|
+
WITH CHECK (true);
|
|
123
|
+
|
|
124
|
+
-- Task XP awards: read-only for anon (written by award_task_xp RPC)
|
|
125
|
+
CREATE POLICY "anon_read_task_xp_awards" ON task_xp_awards
|
|
126
|
+
FOR SELECT TO anon
|
|
127
|
+
USING (true);
|
|
128
|
+
|
|
129
|
+
-- ============================================================
|
|
130
|
+
-- 6. QUESTS: Allow create, join, progress, complete
|
|
131
|
+
-- ============================================================
|
|
132
|
+
|
|
133
|
+
CREATE POLICY "anon_read_quests" ON quests
|
|
134
|
+
FOR SELECT TO anon
|
|
135
|
+
USING (true);
|
|
136
|
+
|
|
137
|
+
CREATE POLICY "anon_insert_quests" ON quests
|
|
138
|
+
FOR INSERT TO anon
|
|
139
|
+
WITH CHECK (true);
|
|
140
|
+
|
|
141
|
+
CREATE POLICY "anon_update_quests" ON quests
|
|
142
|
+
FOR UPDATE TO anon
|
|
143
|
+
USING (true)
|
|
144
|
+
WITH CHECK (true);
|
|
145
|
+
|
|
146
|
+
CREATE POLICY "anon_read_quest_participants" ON quest_participants
|
|
147
|
+
FOR SELECT TO anon
|
|
148
|
+
USING (true);
|
|
149
|
+
|
|
150
|
+
CREATE POLICY "anon_insert_quest_participants" ON quest_participants
|
|
151
|
+
FOR INSERT TO anon
|
|
152
|
+
WITH CHECK (true);
|
|
153
|
+
|
|
154
|
+
CREATE POLICY "anon_read_quest_completions" ON quest_completions
|
|
155
|
+
FOR SELECT TO anon
|
|
156
|
+
USING (true);
|
|
157
|
+
|
|
158
|
+
CREATE POLICY "anon_insert_quest_completions" ON quest_completions
|
|
159
|
+
FOR INSERT TO anon
|
|
160
|
+
WITH CHECK (true);
|
|
161
|
+
|
|
162
|
+
-- ============================================================
|
|
163
|
+
-- 7. LINK CODES & OTP: Allow MCP to create codes
|
|
164
|
+
-- ============================================================
|
|
165
|
+
|
|
166
|
+
CREATE POLICY "anon_read_link_codes" ON link_codes
|
|
167
|
+
FOR SELECT TO anon
|
|
168
|
+
USING (true);
|
|
169
|
+
|
|
170
|
+
CREATE POLICY "anon_insert_link_codes" ON link_codes
|
|
171
|
+
FOR INSERT TO anon
|
|
172
|
+
WITH CHECK (true);
|
|
173
|
+
|
|
174
|
+
CREATE POLICY "anon_update_link_codes" ON link_codes
|
|
175
|
+
FOR UPDATE TO anon
|
|
176
|
+
USING (true)
|
|
177
|
+
WITH CHECK (true);
|
|
178
|
+
|
|
179
|
+
-- OTP codes (if table exists with RLS enabled)
|
|
180
|
+
DO $$
|
|
181
|
+
BEGIN
|
|
182
|
+
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = 'otp_codes') THEN
|
|
183
|
+
EXECUTE 'CREATE POLICY "anon_read_otp_codes" ON otp_codes FOR SELECT TO anon USING (true)';
|
|
184
|
+
EXECUTE 'CREATE POLICY "anon_insert_otp_codes" ON otp_codes FOR INSERT TO anon WITH CHECK (true)';
|
|
185
|
+
EXECUTE 'CREATE POLICY "anon_update_otp_codes" ON otp_codes FOR UPDATE TO anon USING (true) WITH CHECK (true)';
|
|
186
|
+
EXECUTE 'CREATE POLICY "anon_delete_otp_codes" ON otp_codes FOR DELETE TO anon USING (true)';
|
|
187
|
+
END IF;
|
|
188
|
+
END $$;
|
|
189
|
+
|
|
190
|
+
-- ============================================================
|
|
191
|
+
-- 8. METRICS: Allow reporting and processing
|
|
192
|
+
-- ============================================================
|
|
193
|
+
|
|
194
|
+
CREATE POLICY "anon_read_metrics_log" ON metrics_log
|
|
195
|
+
FOR SELECT TO anon
|
|
196
|
+
USING (true);
|
|
197
|
+
|
|
198
|
+
CREATE POLICY "anon_insert_metrics_log" ON metrics_log
|
|
199
|
+
FOR INSERT TO anon
|
|
200
|
+
WITH CHECK (true);
|
|
201
|
+
|
|
202
|
+
CREATE POLICY "anon_update_metrics_log" ON metrics_log
|
|
203
|
+
FOR UPDATE TO anon
|
|
204
|
+
USING (true)
|
|
205
|
+
WITH CHECK (true);
|
|
206
|
+
|
|
207
|
+
-- ============================================================
|
|
208
|
+
-- 9. WEEKLY BONUSES: Allow processing
|
|
209
|
+
-- ============================================================
|
|
210
|
+
|
|
211
|
+
CREATE POLICY "anon_read_weekly_bonus_awards" ON weekly_bonus_awards
|
|
212
|
+
FOR SELECT TO anon
|
|
213
|
+
USING (true);
|
|
214
|
+
|
|
215
|
+
CREATE POLICY "anon_insert_weekly_bonus_awards" ON weekly_bonus_awards
|
|
216
|
+
FOR INSERT TO anon
|
|
217
|
+
WITH CHECK (true);
|
|
218
|
+
|
|
219
|
+
-- Weekly bonus progress (if exists)
|
|
220
|
+
DO $$
|
|
221
|
+
BEGIN
|
|
222
|
+
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = 'weekly_bonus_progress') THEN
|
|
223
|
+
EXECUTE 'CREATE POLICY "anon_read_weekly_bonus_progress" ON weekly_bonus_progress FOR SELECT TO anon USING (true)';
|
|
224
|
+
EXECUTE 'CREATE POLICY "anon_insert_weekly_bonus_progress" ON weekly_bonus_progress FOR INSERT TO anon WITH CHECK (true)';
|
|
225
|
+
EXECUTE 'CREATE POLICY "anon_update_weekly_bonus_progress" ON weekly_bonus_progress FOR UPDATE TO anon USING (true) WITH CHECK (true)';
|
|
226
|
+
END IF;
|
|
227
|
+
END $$;
|
|
228
|
+
|
|
229
|
+
-- ============================================================
|
|
230
|
+
-- 10. XP LEDGER: READ-ONLY for anon (LOCKED)
|
|
231
|
+
-- ============================================================
|
|
232
|
+
-- xp_ledger has NO anon insert/update policy — this is correct.
|
|
233
|
+
-- All XP writes go through SECURITY DEFINER RPCs:
|
|
234
|
+
-- - award_task_xp (task completion)
|
|
235
|
+
-- - check_and_apply_level_up (level progression)
|
|
236
|
+
--
|
|
237
|
+
-- The awardXpWithLock() function in quests.ts writes directly
|
|
238
|
+
-- to xp_ledger — this will FAIL with anon key. It must be
|
|
239
|
+
-- migrated to a SECURITY DEFINER RPC. See migration note below.
|
|
240
|
+
|
|
241
|
+
CREATE POLICY "anon_read_xp_ledger" ON xp_ledger
|
|
242
|
+
FOR SELECT TO anon
|
|
243
|
+
USING (true);
|
|
244
|
+
|
|
245
|
+
-- ============================================================
|
|
246
|
+
-- 11. ADMIN-ONLY TABLES: No anon write (use service_role key)
|
|
247
|
+
-- ============================================================
|
|
248
|
+
-- These tables have anon SELECT but intentionally NO anon write:
|
|
249
|
+
-- - task_types (create_task_type is admin-only)
|
|
250
|
+
-- - xp_config (set_xp_config is admin-only)
|
|
251
|
+
-- - xp_split_rules / xp_split_rule_entries (create_split_rule is admin-only)
|
|
252
|
+
-- - level_curves, rank_definitions, completion_curves
|
|
253
|
+
-- - skill_categories, skill_leveling_rules, skill_tool_mappings
|
|
254
|
+
-- - achievement_definitions, community_expectations
|
|
255
|
+
--
|
|
256
|
+
-- Admin tools (Section 12) must use service_role key to write to these.
|
|
257
|
+
|
|
258
|
+
-- ============================================================
|
|
259
|
+
-- 12. ENSURE RPCs ARE SECURITY DEFINER
|
|
260
|
+
-- ============================================================
|
|
261
|
+
-- These functions must bypass RLS to update locked XP/level columns.
|
|
262
|
+
-- Run these ALTER statements to confirm they're SECURITY DEFINER:
|
|
263
|
+
|
|
264
|
+
ALTER FUNCTION award_task_xp(uuid) SECURITY DEFINER;
|
|
265
|
+
ALTER FUNCTION check_and_apply_level_up(text, uuid) SECURITY DEFINER;
|
|
266
|
+
|
|
267
|
+
-- ============================================================
|
|
268
|
+
-- MIGRATION NOTE: awardXpWithLock() needs an RPC
|
|
269
|
+
-- ============================================================
|
|
270
|
+
-- The quest/weekly-bonus XP path in the MCP server currently
|
|
271
|
+
-- writes directly to xp_ledger and updates users.main_xp / agents.xp.
|
|
272
|
+
-- With these RLS policies, that path will fail for anon.
|
|
273
|
+
--
|
|
274
|
+
-- TODO: Create a new SECURITY DEFINER RPC:
|
|
275
|
+
--
|
|
276
|
+
-- CREATE OR REPLACE FUNCTION award_xp_direct(
|
|
277
|
+
-- p_entity_type TEXT,
|
|
278
|
+
-- p_entity_id UUID,
|
|
279
|
+
-- p_amount INTEGER,
|
|
280
|
+
-- p_source_type TEXT,
|
|
281
|
+
-- p_description TEXT,
|
|
282
|
+
-- p_source_id UUID DEFAULT NULL
|
|
283
|
+
-- ) RETURNS JSONB AS $$
|
|
284
|
+
-- DECLARE
|
|
285
|
+
-- v_running_total BIGINT;
|
|
286
|
+
-- BEGIN
|
|
287
|
+
-- SELECT COALESCE(running_total, 0) INTO v_running_total
|
|
288
|
+
-- FROM xp_ledger
|
|
289
|
+
-- WHERE entity_type = p_entity_type AND entity_id = p_entity_id
|
|
290
|
+
-- ORDER BY created_at DESC LIMIT 1;
|
|
291
|
+
--
|
|
292
|
+
-- v_running_total := v_running_total + p_amount;
|
|
293
|
+
--
|
|
294
|
+
-- INSERT INTO xp_ledger (entity_type, entity_id, xp_type, amount,
|
|
295
|
+
-- source_type, source_id, description, running_total)
|
|
296
|
+
-- VALUES (p_entity_type, p_entity_id, 'main', p_amount,
|
|
297
|
+
-- p_source_type, p_source_id, p_description, v_running_total);
|
|
298
|
+
--
|
|
299
|
+
-- IF p_entity_type = 'user' THEN
|
|
300
|
+
-- UPDATE users SET main_xp = v_running_total WHERE id = p_entity_id;
|
|
301
|
+
-- ELSE
|
|
302
|
+
-- UPDATE agents SET xp = v_running_total WHERE id = p_entity_id;
|
|
303
|
+
-- END IF;
|
|
304
|
+
--
|
|
305
|
+
-- RETURN jsonb_build_object('success', true, 'running_total', v_running_total);
|
|
306
|
+
-- END;
|
|
307
|
+
-- $$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
308
|
+
--
|
|
309
|
+
-- Then update quests.ts awardXpWithLock() to call this RPC instead
|
|
310
|
+
-- of writing directly to xp_ledger.
|
|
311
|
+
-- ============================================================
|