@nextsparkjs/ai-workflow 0.1.0-beta.100

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.
Files changed (272) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -0
  3. package/claude/_docs/workflows-optimizations.md +359 -0
  4. package/claude/agents/api-tester.md +634 -0
  5. package/claude/agents/architecture-supervisor.md +1351 -0
  6. package/claude/agents/backend-developer.md +997 -0
  7. package/claude/agents/backend-validator.md +417 -0
  8. package/claude/agents/bdd-docs-writer.md +737 -0
  9. package/claude/agents/block-developer.md +677 -0
  10. package/claude/agents/code-reviewer.md +1432 -0
  11. package/claude/agents/db-developer.md +721 -0
  12. package/claude/agents/db-validator.md +407 -0
  13. package/claude/agents/demo-video-generator.md +493 -0
  14. package/claude/agents/documentation-writer.md +1268 -0
  15. package/claude/agents/frontend-developer.md +1234 -0
  16. package/claude/agents/frontend-validator.md +777 -0
  17. package/claude/agents/functional-validator.md +630 -0
  18. package/claude/agents/mock-analyst.md +387 -0
  19. package/claude/agents/product-manager.md +963 -0
  20. package/claude/agents/qa-automation.md +1762 -0
  21. package/claude/agents/release-manager.md +634 -0
  22. package/claude/agents/selectors-translator.md +262 -0
  23. package/claude/agents/unit-test-writer.md +785 -0
  24. package/claude/agents/visual-comparator.md +329 -0
  25. package/claude/agents/workflow-maintainer.md +352 -0
  26. package/claude/commands/do/README.md +88 -0
  27. package/claude/commands/do/create-api.md +64 -0
  28. package/claude/commands/do/create-entity.md +66 -0
  29. package/claude/commands/do/create-migration.md +64 -0
  30. package/claude/commands/do/create-plugin.md +56 -0
  31. package/claude/commands/do/create-theme.md +70 -0
  32. package/claude/commands/do/mock-data.md +67 -0
  33. package/claude/commands/do/reset-db.md +71 -0
  34. package/claude/commands/do/setup-scheduled-action.md +75 -0
  35. package/claude/commands/do/sync-code-review.md +117 -0
  36. package/claude/commands/do/update-selectors.md +112 -0
  37. package/claude/commands/do/use-skills.md +90 -0
  38. package/claude/commands/do/validate-blocks.md +69 -0
  39. package/claude/commands/how-to/README.md +261 -0
  40. package/claude/commands/how-to/add-metadata.md +692 -0
  41. package/claude/commands/how-to/add-taxonomies.md +806 -0
  42. package/claude/commands/how-to/add-translations.md +571 -0
  43. package/claude/commands/how-to/create-api.md +577 -0
  44. package/claude/commands/how-to/create-block.md +575 -0
  45. package/claude/commands/how-to/create-child-entities.md +771 -0
  46. package/claude/commands/how-to/create-entity.md +597 -0
  47. package/claude/commands/how-to/create-migrations.md +605 -0
  48. package/claude/commands/how-to/create-plugin.md +654 -0
  49. package/claude/commands/how-to/customize-app.md +481 -0
  50. package/claude/commands/how-to/customize-dashboard.md +553 -0
  51. package/claude/commands/how-to/customize-theme.md +438 -0
  52. package/claude/commands/how-to/define-features-flows.md +632 -0
  53. package/claude/commands/how-to/deploy.md +507 -0
  54. package/claude/commands/how-to/handle-file-uploads.md +746 -0
  55. package/claude/commands/how-to/implement-search.md +1001 -0
  56. package/claude/commands/how-to/install-plugins.md +352 -0
  57. package/claude/commands/how-to/manage-test-coverage.md +984 -0
  58. package/claude/commands/how-to/run-tests.md +400 -0
  59. package/claude/commands/how-to/set-app-languages.md +601 -0
  60. package/claude/commands/how-to/set-plans-and-permissions.md +575 -0
  61. package/claude/commands/how-to/set-scheduled-actions.md +527 -0
  62. package/claude/commands/how-to/set-user-roles-and-permissions.md +550 -0
  63. package/claude/commands/how-to/setup-authentication.md +388 -0
  64. package/claude/commands/how-to/setup-claude-code.md +440 -0
  65. package/claude/commands/how-to/setup-database.md +274 -0
  66. package/claude/commands/how-to/setup-email-providers.md +598 -0
  67. package/claude/commands/how-to/setup-mobile-dev.md +627 -0
  68. package/claude/commands/how-to/start.md +500 -0
  69. package/claude/commands/how-to/use-devtools.md +639 -0
  70. package/claude/commands/how-to/use-superadmin.md +622 -0
  71. package/claude/commands/session/README.md +193 -0
  72. package/claude/commands/session/block-create.md +190 -0
  73. package/claude/commands/session/block-list.md +203 -0
  74. package/claude/commands/session/block-update.md +192 -0
  75. package/claude/commands/session/block-validate.md +218 -0
  76. package/claude/commands/session/changelog.md +115 -0
  77. package/claude/commands/session/close.md +225 -0
  78. package/claude/commands/session/commit.md +174 -0
  79. package/claude/commands/session/db-entity.md +206 -0
  80. package/claude/commands/session/db-fix.md +212 -0
  81. package/claude/commands/session/db-sample.md +206 -0
  82. package/claude/commands/session/demo.md +178 -0
  83. package/claude/commands/session/doc-bdd.md +207 -0
  84. package/claude/commands/session/doc-feature.md +218 -0
  85. package/claude/commands/session/doc-read.md +225 -0
  86. package/claude/commands/session/execute.md +204 -0
  87. package/claude/commands/session/explain.md +202 -0
  88. package/claude/commands/session/fix-bug.md +210 -0
  89. package/claude/commands/session/fix-build.md +182 -0
  90. package/claude/commands/session/fix-test.md +189 -0
  91. package/claude/commands/session/pending.md +232 -0
  92. package/claude/commands/session/refine.md +188 -0
  93. package/claude/commands/session/resume.md +192 -0
  94. package/claude/commands/session/review.md +192 -0
  95. package/claude/commands/session/scope-change.md +181 -0
  96. package/claude/commands/session/start-blocks.md +347 -0
  97. package/claude/commands/session/start.md +604 -0
  98. package/claude/commands/session/status.md +169 -0
  99. package/claude/commands/session/test-fix.md +221 -0
  100. package/claude/commands/session/test-run.md +203 -0
  101. package/claude/commands/session/test-write.md +242 -0
  102. package/claude/commands/session/validate.md +162 -0
  103. package/claude/config/context.json +40 -0
  104. package/claude/config/github.json +69 -0
  105. package/claude/config/github.schema.json +106 -0
  106. package/claude/config/team.json +46 -0
  107. package/claude/config/team.schema.json +106 -0
  108. package/claude/config/workspace.json +43 -0
  109. package/claude/config/workspace.schema.json +75 -0
  110. package/claude/skills/README.md +228 -0
  111. package/claude/skills/accessibility/SKILL.md +573 -0
  112. package/claude/skills/api-bypass-layers/SKILL.md +550 -0
  113. package/claude/skills/asana-integration/SKILL.md +499 -0
  114. package/claude/skills/better-auth/SKILL.md +666 -0
  115. package/claude/skills/billing-subscriptions/SKILL.md +660 -0
  116. package/claude/skills/block-decision-matrix/SKILL.md +359 -0
  117. package/claude/skills/clickup-integration/SKILL.md +434 -0
  118. package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
  119. package/claude/skills/create-plugin/SKILL.md +425 -0
  120. package/claude/skills/create-theme/SKILL.md +331 -0
  121. package/claude/skills/cypress-api/SKILL.md +511 -0
  122. package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
  123. package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
  124. package/claude/skills/cypress-e2e/SKILL.md +526 -0
  125. package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
  126. package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
  127. package/claude/skills/cypress-selectors/SKILL.md +309 -0
  128. package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
  129. package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
  130. package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
  131. package/claude/skills/database-migrations/SKILL.md +335 -0
  132. package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
  133. package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
  134. package/claude/skills/design-system/SKILL.md +682 -0
  135. package/claude/skills/documentation/SKILL.md +540 -0
  136. package/claude/skills/entity-api/SKILL.md +482 -0
  137. package/claude/skills/entity-system/SKILL.md +635 -0
  138. package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
  139. package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
  140. package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
  141. package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
  142. package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
  143. package/claude/skills/github/SKILL.md +467 -0
  144. package/claude/skills/i18n-nextintl/SKILL.md +302 -0
  145. package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
  146. package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
  147. package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
  148. package/claude/skills/impact-analysis/SKILL.md +203 -0
  149. package/claude/skills/jest-unit/SKILL.md +306 -0
  150. package/claude/skills/jest-unit/references/component-testing.md +371 -0
  151. package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
  152. package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
  153. package/claude/skills/jira-integration/SKILL.md +539 -0
  154. package/claude/skills/media-library/SKILL.md +743 -0
  155. package/claude/skills/mock-analysis/SKILL.md +276 -0
  156. package/claude/skills/monorepo-architecture/SKILL.md +162 -0
  157. package/claude/skills/nextjs-api-development/SKILL.md +364 -0
  158. package/claude/skills/nextjs-api-development/scripts/generate-crud-tests.py +456 -0
  159. package/claude/skills/nextjs-api-development/scripts/scaffold-endpoint.py +481 -0
  160. package/claude/skills/nextjs-api-development/scripts/validate-api.py +283 -0
  161. package/claude/skills/notion-integration/SKILL.md +641 -0
  162. package/claude/skills/npm-development-workflow/SKILL.md +480 -0
  163. package/claude/skills/page-builder-blocks/SKILL.md +530 -0
  164. package/claude/skills/page-builder-blocks/scripts/scaffold-block.py +444 -0
  165. package/claude/skills/permissions-system/SKILL.md +619 -0
  166. package/claude/skills/plugins/SKILL.md +340 -0
  167. package/claude/skills/plugins/references/plugin-templates.md +414 -0
  168. package/claude/skills/plugins/references/plugin-testing.md +353 -0
  169. package/claude/skills/plugins/references/plugin-types.md +198 -0
  170. package/claude/skills/plugins/scripts/scaffold-plugin.py +443 -0
  171. package/claude/skills/pom-patterns/SKILL.md +452 -0
  172. package/claude/skills/pom-patterns/scripts/generate-pom.py +392 -0
  173. package/claude/skills/rate-limiting/SKILL.md +342 -0
  174. package/claude/skills/react-best-practices/AGENTS.md +2410 -0
  175. package/claude/skills/react-best-practices/README.md +123 -0
  176. package/claude/skills/react-best-practices/SKILL.md +125 -0
  177. package/claude/skills/react-best-practices/metadata.json +15 -0
  178. package/claude/skills/react-best-practices/rules/_sections.md +46 -0
  179. package/claude/skills/react-best-practices/rules/_template.md +28 -0
  180. package/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  181. package/claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  182. package/claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
  183. package/claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
  184. package/claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
  185. package/claude/skills/react-best-practices/rules/async-parallel.md +28 -0
  186. package/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  187. package/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  188. package/claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  189. package/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  190. package/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  191. package/claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
  192. package/claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  193. package/claude/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  194. package/claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  195. package/claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  196. package/claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  197. package/claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  198. package/claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  199. package/claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  200. package/claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  201. package/claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
  202. package/claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  203. package/claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
  204. package/claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  205. package/claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  206. package/claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  207. package/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  208. package/claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
  209. package/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  210. package/claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  211. package/claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  212. package/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  213. package/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  214. package/claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  215. package/claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  216. package/claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  217. package/claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  218. package/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  219. package/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  220. package/claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
  221. package/claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  222. package/claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  223. package/claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  224. package/claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
  225. package/claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  226. package/claude/skills/react-best-practices/rules/server-serialization.md +38 -0
  227. package/claude/skills/react-patterns/SKILL.md +688 -0
  228. package/claude/skills/registry-system/SKILL.md +331 -0
  229. package/claude/skills/scheduled-actions/SKILL.md +671 -0
  230. package/claude/skills/scope-enforcement/SKILL.md +542 -0
  231. package/claude/skills/scope-enforcement/scripts/validate-scope.py +357 -0
  232. package/claude/skills/server-actions/SKILL.md +493 -0
  233. package/claude/skills/service-layer/SKILL.md +587 -0
  234. package/claude/skills/session-management/SKILL.md +266 -0
  235. package/claude/skills/session-management/scripts/create-session.py +166 -0
  236. package/claude/skills/session-management/scripts/iteration-close.sh +105 -0
  237. package/claude/skills/session-management/scripts/iteration-init.sh +180 -0
  238. package/claude/skills/session-management/scripts/session-archive.sh +87 -0
  239. package/claude/skills/session-management/scripts/session-close.sh +133 -0
  240. package/claude/skills/session-management/scripts/session-init.sh +225 -0
  241. package/claude/skills/session-management/scripts/session-list.sh +163 -0
  242. package/claude/skills/session-management/scripts/split-plan.sh +116 -0
  243. package/claude/skills/shadcn-components/SKILL.md +586 -0
  244. package/claude/skills/shadcn-theming/SKILL.md +446 -0
  245. package/claude/skills/suspense-loading/SKILL.md +280 -0
  246. package/claude/skills/tailwind-theming/SKILL.md +507 -0
  247. package/claude/skills/tanstack-query/SKILL.md +608 -0
  248. package/claude/skills/test-coverage/SKILL.md +239 -0
  249. package/claude/skills/web-design-guidelines/SKILL.md +39 -0
  250. package/claude/skills/zod-validation/SKILL.md +537 -0
  251. package/claude/templates/blocks/progress.md +86 -0
  252. package/claude/templates/iteration/changes.md +61 -0
  253. package/claude/templates/iteration/progress.md +55 -0
  254. package/claude/templates/log.md +31 -0
  255. package/claude/templates/story/context.md +77 -0
  256. package/claude/templates/story/pendings.md +37 -0
  257. package/claude/templates/story/plan.md +299 -0
  258. package/claude/templates/story/requirements.md +109 -0
  259. package/claude/templates/story/scope.json +10 -0
  260. package/claude/templates/story/tests.md +91 -0
  261. package/claude/templates/task/progress.md +58 -0
  262. package/claude/templates/task/requirements.md +54 -0
  263. package/claude/workflows/README.md +154 -0
  264. package/claude/workflows/blocks.md +614 -0
  265. package/claude/workflows/story.md +1207 -0
  266. package/claude/workflows/task.md +927 -0
  267. package/claude/workflows/tweak.md +527 -0
  268. package/cursor/.gitkeep +0 -0
  269. package/package.json +35 -0
  270. package/scripts/postinstall.mjs +198 -0
  271. package/scripts/setup.mjs +282 -0
  272. package/scripts/sync.mjs +209 -0
@@ -0,0 +1,619 @@
1
+ ---
2
+ name: permissions-system
3
+ description: |
4
+ Three-layer permission system (Team Roles + Plans + Quotas) for this Next.js application.
5
+ Covers user roles, team roles, theme extensions, permission checking, and RLS integration.
6
+ Use this skill when implementing or modifying access control features.
7
+ allowed-tools: Read, Glob, Grep
8
+ version: 1.0.0
9
+ ---
10
+
11
+ # Permissions System Skill
12
+
13
+ Three-layer permission architecture for role-based access control, feature gating, and usage limits.
14
+
15
+ ## Architecture Overview
16
+
17
+ ```
18
+ THREE-LAYER PERMISSION SYSTEM:
19
+
20
+ Layer 1: Team Roles (RBAC)
21
+ ├── Core roles: owner (100), admin (50), member (10), viewer (1)
22
+ ├── Theme can extend: editor, contributor, moderator, etc.
23
+ └── Permissions defined in permissions.config.ts
24
+
25
+ Layer 2: Plans (Feature Gating)
26
+ ├── Subscription-based feature access
27
+ ├── Plan features defined in plans.config.ts
28
+ └── Checked via membership.hasFeature()
29
+
30
+ Layer 3: Quotas (Usage Limits)
31
+ ├── Per-plan usage tracking
32
+ ├── Enforced via membership.checkQuota()
33
+ └── Tracked in usage table
34
+
35
+ core/lib/permissions/
36
+ ├── types.ts # Permission type definitions
37
+ ├── check.ts # Server-side permission checks
38
+ ├── hooks.ts # Frontend permission hooks
39
+ ├── system.ts # Core system permissions
40
+ └── merge.ts # Configuration merging
41
+
42
+ core/lib/services/
43
+ ├── permission.service.ts # O(1) permission lookups
44
+ └── membership.service.ts # Complete membership context
45
+ ```
46
+
47
+ ## When to Use This Skill
48
+
49
+ - Implementing role-based access control
50
+ - Adding entity permissions
51
+ - Extending team roles in themes
52
+ - Checking permissions in API routes
53
+ - Rendering UI based on permissions
54
+ - Working with feature flags and quotas
55
+
56
+ ## User Roles vs Team Roles
57
+
58
+ ### CRITICAL: Understanding the Two Role Systems
59
+
60
+ This application uses **two completely separate role systems** for different purposes:
61
+
62
+ | Aspect | User Roles | Team Roles |
63
+ |--------|------------|------------|
64
+ | **Storage** | `user.role` column | `teamMembers.role` column |
65
+ | **Scope** | Global (entire app) | Per-team membership |
66
+ | **Extensible** | ❌ **NO** - Hardcoded in core | ✅ **YES** - Themes add custom roles |
67
+ | **Purpose** | Route access control | Entity permissions |
68
+ | **Checked by** | Middleware, roleHelpers | MembershipService |
69
+
70
+ ### User Roles (App-Level, FIXED - NOT Extensible)
71
+
72
+ ```typescript
73
+ // 3 fixed system roles - CANNOT be extended by themes
74
+ // Defined in: core/types/user.types.ts
75
+ type UserRole = 'member' | 'superadmin' | 'developer'
76
+ ```
77
+
78
+ | Role | Hierarchy | Access | Routes |
79
+ |------|-----------|--------|--------|
80
+ | `member` | 1 | Standard authenticated user | `/dashboard/*` |
81
+ | `superadmin` | 99 | System admin, bypasses team permissions | `/superadmin/*` |
82
+ | `developer` | 100 | Full access, debugging APIs | `/devtools/*` |
83
+
84
+ **Why NOT extensible:**
85
+ - Security: Route protection must be predictable
86
+ - Core functionality: Middleware relies on fixed set
87
+ - System integrity: Themes cannot grant system-level access
88
+
89
+ **Check user role:**
90
+ ```typescript
91
+ import { roleHelpers } from '@/core/lib/role-helpers'
92
+
93
+ // CORRECT: Use roleHelpers for user roles
94
+ if (roleHelpers.isDeveloper(user.role)) {
95
+ // Access to /devtools/*
96
+ }
97
+ if (roleHelpers.isSuperAdmin(user.role)) {
98
+ // Access to /superadmin/*, bypasses team checks
99
+ }
100
+
101
+ // WRONG: Never check user roles via membership
102
+ if (membership.hasRole('superadmin')) {} // This checks TEAM role, not user role!
103
+ ```
104
+
105
+ ### Team Roles (Team-Level, EXTENSIBLE by Themes)
106
+
107
+ ```typescript
108
+ // Core team roles (protected, always available)
109
+ type CoreTeamRole = 'owner' | 'admin' | 'member' | 'viewer'
110
+
111
+ // Theme can add custom roles
112
+ type TeamRole = CoreTeamRole | 'editor' | 'contributor' | 'moderator' | string
113
+ ```
114
+
115
+ | Role | Hierarchy | Description | Extensible |
116
+ |------|-----------|-------------|------------|
117
+ | `owner` | 100 | Team creator, all permissions, cannot be removed | ❌ Core |
118
+ | `admin` | 50 | Team management, member roles, billing | ❌ Core |
119
+ | `member` | 10 | Standard entity access | ❌ Core |
120
+ | `viewer` | 1 | Read-only access | ❌ Core |
121
+ | `editor` | 5 | Theme-defined: Edit without delete | ✅ Theme |
122
+ | `contributor` | 3 | Theme-defined: Limited create/edit | ✅ Theme |
123
+ | `moderator` | 7 | Theme-defined: Content moderation | ✅ Theme |
124
+
125
+ ### Complete Example: Adding Custom Team Roles
126
+
127
+ ```typescript
128
+ // contents/themes/your-theme/config/permissions.config.ts
129
+ import type { ThemePermissionsConfig } from '@/core/lib/permissions/types'
130
+
131
+ export const PERMISSIONS_CONFIG_OVERRIDES: ThemePermissionsConfig = {
132
+ // 1. Define custom team roles
133
+ roles: {
134
+ additionalRoles: ['editor', 'contributor', 'moderator'] as const,
135
+ hierarchy: {
136
+ editor: 5, // Between viewer (1) and member (10)
137
+ contributor: 3, // Above viewer, below editor
138
+ moderator: 7, // Above editor, below member
139
+ },
140
+ displayNames: {
141
+ editor: 'common.teamRoles.editor', // i18n key
142
+ contributor: 'common.teamRoles.contributor',
143
+ moderator: 'common.teamRoles.moderator',
144
+ },
145
+ descriptions: {
146
+ editor: 'Can view and edit content without delete access',
147
+ contributor: 'Can create and edit own content only',
148
+ moderator: 'Can moderate content and manage comments',
149
+ },
150
+ },
151
+
152
+ // 2. Define which roles can perform which actions (object format, not array)
153
+ entities: {
154
+ products: [
155
+ { action: 'read', roles: ['owner', 'admin', 'member', 'editor', 'contributor', 'moderator', 'viewer'] },
156
+ { action: 'create', roles: ['owner', 'admin', 'member', 'editor', 'contributor'] },
157
+ { action: 'update', roles: ['owner', 'admin', 'member', 'editor'] },
158
+ { action: 'delete', roles: ['owner', 'admin'] },
159
+ { action: 'moderate', roles: ['owner', 'admin', 'moderator'] },
160
+ ],
161
+ },
162
+
163
+ // 3. Define team-level permissions
164
+ teams: [
165
+ { action: 'team.view', roles: ['owner', 'admin', 'member', 'editor', 'contributor', 'moderator', 'viewer'] },
166
+ { action: 'team.edit', roles: ['owner', 'admin'] },
167
+ { action: 'team.members.invite', roles: ['owner', 'admin'] },
168
+ { action: 'team.members.remove', roles: ['owner', 'admin'] },
169
+ { action: 'team.members.changeRole', roles: ['owner', 'admin'] },
170
+ { action: 'team.delete', roles: ['owner'], dangerous: true },
171
+ ],
172
+ }
173
+ ```
174
+
175
+ ### Translations for Custom Roles
176
+
177
+ ```json
178
+ // contents/themes/your-theme/messages/en.json
179
+ {
180
+ "common": {
181
+ "teamRoles": {
182
+ "editor": "Editor",
183
+ "contributor": "Contributor",
184
+ "moderator": "Moderator"
185
+ }
186
+ }
187
+ }
188
+
189
+ // contents/themes/your-theme/messages/es.json
190
+ {
191
+ "common": {
192
+ "teamRoles": {
193
+ "editor": "Editor",
194
+ "contributor": "Colaborador",
195
+ "moderator": "Moderador"
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ **IMPORTANT:** Core roles (`owner`, `admin`, `member`, `viewer`) translations are in `core/messages/`. Theme MUST NOT redefine them.
202
+
203
+ ## Permission Format
204
+
205
+ ```typescript
206
+ // Pattern: "[scope].[action]"
207
+ type Permission = `${string}.${string}`
208
+
209
+ // Entity permissions
210
+ 'customers.create'
211
+ 'customers.read'
212
+ 'customers.update'
213
+ 'customers.delete'
214
+
215
+ // Team permissions
216
+ 'team.view'
217
+ 'team.edit'
218
+ 'team.members.invite'
219
+ 'team.members.remove'
220
+ 'team.delete'
221
+
222
+ // Feature permissions
223
+ 'page-builder.access'
224
+ 'page-builder.custom-css'
225
+ 'api-keys.manage'
226
+ ```
227
+
228
+ ## Theme Extension Pattern
229
+
230
+ ### permissions.config.ts
231
+
232
+ ```typescript
233
+ // contents/themes/default/config/permissions.config.ts
234
+ import type { ThemePermissionsConfig } from '@/core/lib/permissions/types'
235
+
236
+ export const PERMISSIONS_CONFIG_OVERRIDES: ThemePermissionsConfig = {
237
+ // 1. Add custom team roles
238
+ roles: {
239
+ additionalRoles: ['editor'] as const,
240
+ hierarchy: { editor: 5 }, // Between viewer (1) and member (10)
241
+ displayNames: {
242
+ editor: 'common.teamRoles.editor', // i18n key
243
+ },
244
+ descriptions: {
245
+ editor: 'Can view and edit content with limited access',
246
+ },
247
+ },
248
+
249
+ // 2. Team-level permissions
250
+ teams: [
251
+ { action: 'team.view', roles: ['owner', 'admin', 'member', 'viewer', 'editor'] },
252
+ { action: 'team.edit', roles: ['owner', 'admin'] },
253
+ { action: 'team.members.invite', roles: ['owner', 'admin'] },
254
+ { action: 'team.members.remove', roles: ['owner', 'admin'] },
255
+ { action: 'team.delete', roles: ['owner'], dangerous: true },
256
+ ],
257
+
258
+ // 3. Entity permissions (entity.action format)
259
+ entities: {
260
+ customers: [
261
+ { action: 'create', roles: ['owner', 'admin'], label: 'Create customers' },
262
+ { action: 'read', roles: ['owner', 'admin', 'member', 'editor'] },
263
+ { action: 'update', roles: ['owner', 'admin', 'member'] },
264
+ { action: 'delete', roles: ['owner'], dangerous: true },
265
+ ],
266
+ tasks: [
267
+ { action: 'create', roles: ['owner', 'admin', 'member'] },
268
+ { action: 'read', roles: ['owner', 'admin', 'member'] },
269
+ { action: 'update', roles: ['owner', 'admin', 'member'] },
270
+ { action: 'delete', roles: ['owner', 'admin'] },
271
+ // Note: 'editor' intentionally excluded from tasks
272
+ ],
273
+ },
274
+
275
+ // 4. Feature permissions
276
+ features: [
277
+ {
278
+ action: 'page-builder.access',
279
+ roles: ['owner', 'admin', 'editor', 'member'],
280
+ label: 'Access Page Builder',
281
+ },
282
+ {
283
+ action: 'page-builder.custom-css',
284
+ roles: ['owner', 'admin'],
285
+ dangerous: true,
286
+ label: 'Use custom CSS',
287
+ },
288
+ ],
289
+
290
+ // 5. Override or disable core permissions (optional)
291
+ overrides: {
292
+ // Override specific permission config
293
+ },
294
+ disabled: [
295
+ // Disable specific core permissions
296
+ ],
297
+ }
298
+ ```
299
+
300
+ ## PermissionService
301
+
302
+ ```typescript
303
+ // core/lib/services/permission.service.ts
304
+
305
+ export class PermissionService {
306
+ // Check single permission - O(1)
307
+ static hasPermission(role: string, permission: Permission): boolean
308
+
309
+ // Check any action format (teams.*, entities.*, features.*)
310
+ static canDoAction(role: string, action: string): boolean
311
+
312
+ // Get all permissions for role - O(1)
313
+ static getRolePermissions(role: string): Permission[]
314
+
315
+ // Check multiple permissions
316
+ static hasAnyPermission(role: string, permissions: Permission[]): boolean
317
+ static hasAllPermissions(role: string, permissions: Permission[]): boolean
318
+
319
+ // Get permission configuration
320
+ static getConfig(permission: Permission): ResolvedPermission | undefined
321
+
322
+ // Full matrix for admin UI
323
+ static getMatrix(): { permissions, matrix, sections, roles }
324
+ }
325
+ ```
326
+
327
+ **Usage:**
328
+ ```typescript
329
+ import { PermissionService } from '@/core/lib/services/permission.service'
330
+
331
+ // Check if admin can create customers
332
+ PermissionService.hasPermission('admin', 'customers.create') // true
333
+
334
+ // Check if editor can access tasks
335
+ PermissionService.canDoAction('editor', 'tasks.read') // false
336
+ ```
337
+
338
+ ## MembershipService
339
+
340
+ ```typescript
341
+ // core/lib/services/membership.service.ts
342
+
343
+ // TeamMembership class - returned by MembershipService.get()
344
+ export class TeamMembership {
345
+ // Role checks
346
+ hasMinHierarchy(level: number): boolean
347
+ hasRole(role: string): boolean
348
+ hasAnyRole(roles: string[]): boolean
349
+
350
+ // Permission checks
351
+ hasPermission(permission: Permission): boolean
352
+ hasFeature(feature: string): boolean
353
+
354
+ // Quota checks
355
+ checkQuota(limitSlug: string, increment?: number): { allowed, remaining }
356
+
357
+ // Comprehensive action check (combines all layers)
358
+ canPerformAction(action: string, options?): ActionResult
359
+ }
360
+
361
+ export class MembershipService {
362
+ // Get complete membership context
363
+ static async get(userId: string, teamId: string): Promise<TeamMembership>
364
+ }
365
+ ```
366
+
367
+ **Usage:**
368
+ ```typescript
369
+ import { MembershipService } from '@/core/lib/services/membership.service'
370
+
371
+ const membership = await MembershipService.get(userId, teamId)
372
+
373
+ // Layer 1: RBAC
374
+ if (membership.hasPermission('customers.delete')) {
375
+ // Can delete customers
376
+ }
377
+
378
+ // Layer 2: Plan features
379
+ if (membership.hasFeature('advanced_analytics')) {
380
+ // Show analytics dashboard
381
+ }
382
+
383
+ // Layer 3: Quotas
384
+ const quota = membership.checkQuota('projects', 1)
385
+ if (!quota.allowed) {
386
+ throw new Error('Project limit reached')
387
+ }
388
+
389
+ // Comprehensive check
390
+ const result = membership.canPerformAction('customers.create')
391
+ if (!result.allowed) {
392
+ // result.reason: 'permission_denied' | 'quota_exceeded' | 'feature_disabled'
393
+ throw new Error(result.message)
394
+ }
395
+ ```
396
+
397
+ ## Server-Side Permission Checks
398
+
399
+ ```typescript
400
+ // core/lib/permissions/check.ts
401
+
402
+ // Single permission check
403
+ export async function checkPermission(
404
+ userId: string,
405
+ teamId: string,
406
+ permission: Permission
407
+ ): Promise<boolean>
408
+
409
+ // Multiple permissions (AND - all required)
410
+ export async function checkPermissions(
411
+ userId: string,
412
+ teamId: string,
413
+ permissions: Permission[]
414
+ ): Promise<boolean>
415
+
416
+ // Multiple permissions (OR - any sufficient)
417
+ export async function checkAnyPermission(
418
+ userId: string,
419
+ teamId: string,
420
+ permissions: Permission[]
421
+ ): Promise<boolean>
422
+
423
+ // Synchronous check (when role is known)
424
+ export function hasPermissionSync(
425
+ teamRole: TeamRole,
426
+ permission: Permission
427
+ ): boolean
428
+ ```
429
+
430
+ **API Route Usage:**
431
+ ```typescript
432
+ import { checkPermission } from '@/core/lib/permissions/check'
433
+ import { createApiError } from '@/core/lib/api/response'
434
+
435
+ export async function DELETE(request: NextRequest, { params }) {
436
+ const { userId, teamId } = await getAuthContext(request)
437
+
438
+ // Check permission before action
439
+ const canDelete = await checkPermission(userId, teamId, 'customers.delete')
440
+ if (!canDelete) {
441
+ return createApiError('Permission denied', 403)
442
+ }
443
+
444
+ // Proceed with deletion
445
+ await CustomerService.delete(params.id, userId)
446
+ return createApiResponse({ success: true })
447
+ }
448
+ ```
449
+
450
+ ## Frontend Permission Hooks
451
+
452
+ ```typescript
453
+ // core/lib/permissions/hooks.ts
454
+ 'use client'
455
+
456
+ // Single permission check
457
+ export function usePermission(permission: Permission): boolean
458
+
459
+ // Multiple permissions (returns object)
460
+ export function usePermissions<T extends Record<string, Permission>>(
461
+ permissions: T
462
+ ): Record<keyof T, boolean>
463
+
464
+ // Get all user permissions in team
465
+ export function useAllPermissions(): Permission[]
466
+
467
+ // Get current team role
468
+ export function useTeamRole(): TeamRole | null
469
+ ```
470
+
471
+ **Component Usage:**
472
+ ```typescript
473
+ import { usePermission, usePermissions, useTeamRole } from '@/core/lib/permissions/hooks'
474
+
475
+ function CustomerActions({ customerId }) {
476
+ // Single permission
477
+ const canDelete = usePermission('customers.delete')
478
+
479
+ // Multiple permissions
480
+ const { canEdit, canExport } = usePermissions({
481
+ canEdit: 'customers.update',
482
+ canExport: 'customers.export',
483
+ })
484
+
485
+ // Role-based rendering
486
+ const role = useTeamRole()
487
+
488
+ return (
489
+ <>
490
+ {canEdit && <EditButton id={customerId} />}
491
+ {canDelete && <DeleteButton id={customerId} />}
492
+ {role === 'owner' && <OwnerOnlySettings />}
493
+ </>
494
+ )
495
+ }
496
+ ```
497
+
498
+ ## Entity Permission Actions
499
+
500
+ ```typescript
501
+ // Standard entity actions
502
+ type EntityAction =
503
+ | 'create' // Create new record
504
+ | 'read' // View individual record
505
+ | 'list' // List records
506
+ | 'update' // Edit record
507
+ | 'delete' // Delete record
508
+ | 'export' // Export data
509
+ | 'import' // Import data
510
+ | 'assign' // Assign to user
511
+ | 'publish' // Publish record
512
+ | 'archive' // Archive record
513
+
514
+ // Permission action definition
515
+ interface EntityPermissionAction {
516
+ action: EntityAction | string
517
+ label: string
518
+ description?: string
519
+ roles: TeamRole[]
520
+ dangerous?: boolean
521
+ }
522
+ ```
523
+
524
+ ## RLS Integration
525
+
526
+ Permissions work with Row Level Security at the database level:
527
+
528
+ ```typescript
529
+ // RLS policies use team membership
530
+ CREATE POLICY "users_can_view_own_team_data"
531
+ ON customers
532
+ FOR SELECT
533
+ USING (
534
+ "teamId" IN (
535
+ SELECT "teamId" FROM "teamMembers"
536
+ WHERE "userId" = current_setting('app.user_id')
537
+ )
538
+ );
539
+ ```
540
+
541
+ **Service layer sets RLS context:**
542
+ ```typescript
543
+ import { queryWithRLS } from '@/core/lib/db'
544
+
545
+ // userId passed to set app.user_id for RLS
546
+ const customers = await queryWithRLS(
547
+ 'SELECT * FROM customers WHERE status = $1',
548
+ ['active'],
549
+ userId // Sets app.user_id
550
+ )
551
+ ```
552
+
553
+ ## Build-Time Registry
554
+
555
+ ```typescript
556
+ // core/lib/registries/permissions-registry.ts (AUTO-GENERATED)
557
+
558
+ // Pre-computed at build time for O(1) lookups
559
+ export const ALL_PERMISSIONS: Permission[]
560
+ export const PERMISSIONS_BY_ROLE: Record<TeamRole, Set<Permission>>
561
+ export const PERMISSIONS_BY_CATEGORY: Record<string, ResolvedPermission[]>
562
+ export const TEAM_PERMISSIONS_BY_ROLE: Record<TeamRole, Permission[]>
563
+ ```
564
+
565
+ **Rebuild registry:**
566
+ ```bash
567
+ node core/scripts/build/registry.mjs
568
+ ```
569
+
570
+ ## Anti-Patterns
571
+
572
+ ```typescript
573
+ // NEVER: Hardcode role checks
574
+ if (user.role === 'admin') { /* access */ }
575
+
576
+ // CORRECT: Use permission checks
577
+ if (await checkPermission(userId, teamId, 'customers.delete')) {}
578
+
579
+ // NEVER: Skip permission check on destructive actions
580
+ await CustomerService.delete(id, userId) // Missing permission check!
581
+
582
+ // CORRECT: Always check before destructive actions
583
+ const canDelete = await checkPermission(userId, teamId, 'customers.delete')
584
+ if (!canDelete) throw new Error('Permission denied')
585
+ await CustomerService.delete(id, userId)
586
+
587
+ // NEVER: Mix user roles and team roles
588
+ if (membership.hasRole('superadmin')) {} // Wrong context!
589
+
590
+ // CORRECT: Use appropriate role type
591
+ if (roleHelpers.isSuperAdmin(user.role)) {} // User role
592
+ if (membership.hasRole('admin')) {} // Team role
593
+
594
+ // NEVER: Check permissions client-side only
595
+ // Client checks are for UI, server MUST re-validate
596
+
597
+ // CORRECT: Always validate on server
598
+ // Client: usePermission() for UI
599
+ // Server: checkPermission() for action
600
+ ```
601
+
602
+ ## Checklist
603
+
604
+ Before finalizing permission implementation:
605
+
606
+ - [ ] Uses three-layer check when appropriate (permission + feature + quota)
607
+ - [ ] Server-side checks on all protected routes
608
+ - [ ] Frontend hooks for conditional UI rendering
609
+ - [ ] Entity permissions defined in theme's permissions.config.ts
610
+ - [ ] Custom roles include hierarchy and display names
611
+ - [ ] Dangerous actions marked with `dangerous: true`
612
+ - [ ] RLS policies align with permission model
613
+ - [ ] Registry rebuilt after config changes
614
+
615
+ ## Related Skills
616
+
617
+ - `better-auth` - Authentication patterns
618
+ - `entity-api` - API endpoint patterns
619
+ - `service-layer` - Service patterns with RLS