@famgia/omnify-ai-guides 2.0.15
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/README.md +105 -0
- package/dist/chunk-RCTEXK7C.js +549 -0
- package/dist/chunk-RCTEXK7C.js.map +1 -0
- package/dist/config/rules.yaml +524 -0
- package/dist/index.cjs +587 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +55 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/agents/architect.md.stub +150 -0
- package/dist/knowledge/agents/developer.md.stub +190 -0
- package/dist/knowledge/agents/reviewer.md.stub +134 -0
- package/dist/knowledge/agents/tester.md.stub +196 -0
- package/dist/knowledge/checklists/backend.md.stub +112 -0
- package/dist/knowledge/checklists/react.md.stub +108 -0
- package/dist/knowledge/claude-rules/laravel-controllers.md.stub +57 -0
- package/dist/knowledge/claude-rules/laravel-migrations.md.stub +47 -0
- package/dist/knowledge/claude-rules/laravel-tests.md.stub +52 -0
- package/dist/knowledge/claude-rules/naming.md.stub +369 -0
- package/dist/knowledge/claude-rules/performance.md.stub +256 -0
- package/dist/knowledge/claude-rules/php-standards.md.stub +305 -0
- package/dist/knowledge/claude-rules/react-components.md.stub +67 -0
- package/dist/knowledge/claude-rules/schema-yaml.md.stub +83 -0
- package/dist/knowledge/claude-rules/security.md.stub +164 -0
- package/dist/knowledge/cursor-rules/antd-deprecations.mdc.stub +62 -0
- package/dist/knowledge/cursor-rules/basemodel-readonly.mdc.stub +66 -0
- package/dist/knowledge/cursor-rules/baserequest-readonly.mdc.stub +74 -0
- package/dist/knowledge/cursor-rules/baseresource-readonly.mdc.stub +78 -0
- package/dist/knowledge/cursor-rules/laravel-controller.mdc.stub +421 -0
- package/dist/knowledge/cursor-rules/laravel-request.mdc.stub +112 -0
- package/dist/knowledge/cursor-rules/laravel-resource.mdc.stub +73 -0
- package/dist/knowledge/cursor-rules/laravel-review.mdc.stub +69 -0
- package/dist/knowledge/cursor-rules/laravel-testing.mdc.stub +138 -0
- package/dist/knowledge/cursor-rules/laravel.mdc.stub +138 -0
- package/dist/knowledge/cursor-rules/migrations-workflow.mdc.stub +224 -0
- package/dist/knowledge/cursor-rules/model-editable.mdc.stub +120 -0
- package/dist/knowledge/cursor-rules/omnify-migrations.mdc.stub +109 -0
- package/dist/knowledge/cursor-rules/omnify-schema.mdc.stub +358 -0
- package/dist/knowledge/cursor-rules/omnify.mdc.stub +58 -0
- package/dist/knowledge/cursor-rules/react-design.mdc.stub +693 -0
- package/dist/knowledge/cursor-rules/react-form.mdc.stub +292 -0
- package/dist/knowledge/cursor-rules/react-services.mdc.stub +304 -0
- package/dist/knowledge/cursor-rules/react.mdc.stub +336 -0
- package/dist/knowledge/cursor-rules/request-editable.mdc.stub +111 -0
- package/dist/knowledge/cursor-rules/resource-editable.mdc.stub +125 -0
- package/dist/knowledge/cursor-rules/schema-create.mdc.stub +440 -0
- package/dist/knowledge/cursor-rules/validation-rules.mdc.stub +181 -0
- package/dist/knowledge/laravel/README.md.stub +59 -0
- package/dist/knowledge/laravel/architecture.md.stub +424 -0
- package/dist/knowledge/laravel/authentication.md.stub +588 -0
- package/dist/knowledge/laravel/controller.md.stub +484 -0
- package/dist/knowledge/laravel/datetime.md.stub +334 -0
- package/dist/knowledge/laravel/migrations-team.md.stub +376 -0
- package/dist/knowledge/laravel/openapi.md.stub +449 -0
- package/dist/knowledge/laravel/request.md.stub +450 -0
- package/dist/knowledge/laravel/resource.md.stub +516 -0
- package/dist/knowledge/laravel/service.md.stub +503 -0
- package/dist/knowledge/laravel/testing.md.stub +1504 -0
- package/dist/knowledge/omnify/antdesign-guide.md.stub +401 -0
- package/dist/knowledge/omnify/config-guide.md.stub +405 -0
- package/dist/knowledge/omnify/japan-guide.md.stub +186 -0
- package/dist/knowledge/omnify/laravel-guide.md.stub +61 -0
- package/dist/knowledge/omnify/partial-schema-guide.md.stub +353 -0
- package/dist/knowledge/omnify/react-form-guide.md.stub +225 -0
- package/dist/knowledge/omnify/schema-guide.md.stub +144 -0
- package/dist/knowledge/omnify/typescript-guide.md.stub +337 -0
- package/dist/knowledge/react/README.md.stub +221 -0
- package/dist/knowledge/react/antd-guide.md +528 -0
- package/dist/knowledge/react/antd-guide.md.stub +528 -0
- package/dist/knowledge/react/checklist.md.stub +108 -0
- package/dist/knowledge/react/datetime-guide.md.stub +137 -0
- package/dist/knowledge/react/design-philosophy.md.stub +363 -0
- package/dist/knowledge/react/i18n-guide.md.stub +211 -0
- package/dist/knowledge/react/laravel-integration.md.stub +181 -0
- package/dist/knowledge/react/service-pattern.md.stub +180 -0
- package/dist/knowledge/react/tanstack-query.md.stub +339 -0
- package/dist/knowledge/react/types-guide.md +669 -0
- package/dist/knowledge/react/types-guide.md.stub +669 -0
- package/dist/knowledge/workflows/bug-fix.md.stub +201 -0
- package/dist/knowledge/workflows/code-review.md.stub +164 -0
- package/dist/knowledge/workflows/new-feature.md.stub +327 -0
- package/dist/plugin-M95GyBll.d.cts +191 -0
- package/dist/plugin-M95GyBll.d.ts +191 -0
- package/dist/plugin.cjs +573 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +2 -0
- package/dist/plugin.d.ts +2 -0
- package/dist/plugin.js +15 -0
- package/dist/plugin.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "{{LARAVEL_ROOT}}app/**/*.php"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PHP Standards & Best Practices
|
|
7
|
+
|
|
8
|
+
> **PHP 8+ features** and coding standards for Laravel projects.
|
|
9
|
+
|
|
10
|
+
## 🔵 Strict Types
|
|
11
|
+
|
|
12
|
+
**Always declare strict types at the top of PHP files.**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
<?php
|
|
16
|
+
|
|
17
|
+
declare(strict_types=1);
|
|
18
|
+
|
|
19
|
+
namespace App\Services;
|
|
20
|
+
|
|
21
|
+
// ... class definition
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| Rule | Description |
|
|
25
|
+
| ---- | ----------- |
|
|
26
|
+
| `declare(strict_types=1)` | Required in all PHP files |
|
|
27
|
+
| Place at very top | Before namespace declaration |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 🔵 Constructor Property Promotion (PHP 8.0+)
|
|
32
|
+
|
|
33
|
+
**Use constructor promotion for dependency injection.**
|
|
34
|
+
|
|
35
|
+
```php
|
|
36
|
+
// ❌ OLD STYLE: Verbose
|
|
37
|
+
class UserService
|
|
38
|
+
{
|
|
39
|
+
private UserRepository $repository;
|
|
40
|
+
private CacheManager $cache;
|
|
41
|
+
|
|
42
|
+
public function __construct(UserRepository $repository, CacheManager $cache)
|
|
43
|
+
{
|
|
44
|
+
$this->repository = $repository;
|
|
45
|
+
$this->cache = $cache;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ✅ PHP 8.0+: Constructor promotion
|
|
50
|
+
class UserService
|
|
51
|
+
{
|
|
52
|
+
public function __construct(
|
|
53
|
+
private readonly UserRepository $repository,
|
|
54
|
+
private readonly CacheManager $cache
|
|
55
|
+
) {}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| Modifier | Usage |
|
|
60
|
+
| -------- | ----- |
|
|
61
|
+
| `private readonly` | Immutable dependencies (preferred) |
|
|
62
|
+
| `private` | Mutable internal state |
|
|
63
|
+
| `protected readonly` | For extension by subclasses |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🔵 PHP 8+ Features
|
|
68
|
+
|
|
69
|
+
### Named Arguments
|
|
70
|
+
|
|
71
|
+
```php
|
|
72
|
+
// ✅ Clear intent
|
|
73
|
+
$this->checkEmailLockout(
|
|
74
|
+
email: $request->email,
|
|
75
|
+
checkOnly: true
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// Use when function has many optional parameters
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Nullsafe Operator
|
|
82
|
+
|
|
83
|
+
```php
|
|
84
|
+
// ❌ OLD STYLE
|
|
85
|
+
$country = $user->address ? ($user->address->country ? $user->address->country->name : null) : null;
|
|
86
|
+
|
|
87
|
+
// ✅ PHP 8.0+: Nullsafe operator
|
|
88
|
+
$country = $user->address?->country?->name;
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Union Types
|
|
92
|
+
|
|
93
|
+
```php
|
|
94
|
+
public function process(int|string $id): Response|RedirectResponse
|
|
95
|
+
{
|
|
96
|
+
// ...
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Match Expression
|
|
101
|
+
|
|
102
|
+
```php
|
|
103
|
+
// ❌ OLD: switch statement
|
|
104
|
+
switch ($status) {
|
|
105
|
+
case 'active': return 'Active';
|
|
106
|
+
case 'inactive': return 'Inactive';
|
|
107
|
+
default: return 'Unknown';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ✅ PHP 8.0+: match expression
|
|
111
|
+
return match($status) {
|
|
112
|
+
'active' => 'Active',
|
|
113
|
+
'inactive' => 'Inactive',
|
|
114
|
+
default => 'Unknown',
|
|
115
|
+
};
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 🔵 Constants Organization
|
|
121
|
+
|
|
122
|
+
**Use dedicated Constants classes instead of magic values.**
|
|
123
|
+
|
|
124
|
+
```php
|
|
125
|
+
// ❌ BAD: Magic strings scattered in code
|
|
126
|
+
if ($user->role === 'admin') { ... }
|
|
127
|
+
Cache::get('user:' . $id);
|
|
128
|
+
session()->get('2fa:user_id');
|
|
129
|
+
|
|
130
|
+
// ✅ GOOD: Constants in dedicated class
|
|
131
|
+
namespace App\Constants;
|
|
132
|
+
|
|
133
|
+
class TwoFactorConstants
|
|
134
|
+
{
|
|
135
|
+
public const ENABLED = true;
|
|
136
|
+
public const CODE_LENGTH = 6;
|
|
137
|
+
public const EXPIRY_MINUTES = 5;
|
|
138
|
+
|
|
139
|
+
// Session keys
|
|
140
|
+
public const SESSION_USER_ID = '2fa:user_id';
|
|
141
|
+
public const SESSION_EMAIL = '2fa:email';
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Usage
|
|
145
|
+
use App\Constants\TwoFactorConstants;
|
|
146
|
+
|
|
147
|
+
if (TwoFactorConstants::ENABLED) {
|
|
148
|
+
$code = Str::random(TwoFactorConstants::CODE_LENGTH);
|
|
149
|
+
session()->put(TwoFactorConstants::SESSION_USER_ID, $user->id);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
| Location | Purpose |
|
|
154
|
+
| -------- | ------- |
|
|
155
|
+
| `app/Constants/` | Application-wide constants |
|
|
156
|
+
| Class constants | Domain-specific constants |
|
|
157
|
+
| `config/*.php` | Environment-dependent values |
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 🔵 PHPDoc Standards
|
|
162
|
+
|
|
163
|
+
### Method Documentation
|
|
164
|
+
|
|
165
|
+
```php
|
|
166
|
+
/**
|
|
167
|
+
* Get user's authorization for a service.
|
|
168
|
+
*
|
|
169
|
+
* @param User $user The user to check
|
|
170
|
+
* @param Service $service The service being accessed
|
|
171
|
+
*
|
|
172
|
+
* @return array{
|
|
173
|
+
* organization_id: int,
|
|
174
|
+
* organization_slug: string,
|
|
175
|
+
* role: string,
|
|
176
|
+
* level: int
|
|
177
|
+
* }|null Returns null if user has no access
|
|
178
|
+
*
|
|
179
|
+
* @throws AuthorizationException When service is inactive
|
|
180
|
+
*/
|
|
181
|
+
public function getUserAuthorization(User $user, Service $service): ?array
|
|
182
|
+
{
|
|
183
|
+
// ...
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Array Shape Documentation
|
|
188
|
+
|
|
189
|
+
```php
|
|
190
|
+
/**
|
|
191
|
+
* @return array{
|
|
192
|
+
* id: int,
|
|
193
|
+
* name: string,
|
|
194
|
+
* email: string,
|
|
195
|
+
* roles: string[]
|
|
196
|
+
* }
|
|
197
|
+
*/
|
|
198
|
+
public function toArray(): array
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### When to Document
|
|
202
|
+
|
|
203
|
+
| Document | Don't Document |
|
|
204
|
+
| -------- | -------------- |
|
|
205
|
+
| Complex return types | Obvious getters/setters |
|
|
206
|
+
| Array shapes | Simple CRUD methods |
|
|
207
|
+
| Exception conditions | Self-explanatory code |
|
|
208
|
+
| Business logic | Framework conventions |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 🔵 Code Complexity Limits
|
|
213
|
+
|
|
214
|
+
### Method Guidelines
|
|
215
|
+
|
|
216
|
+
| Metric | Limit | Action if exceeded |
|
|
217
|
+
| ------ | ----- | ------------------ |
|
|
218
|
+
| Lines per method | Max 50 | Extract to helper/service |
|
|
219
|
+
| Parameters | Max 4 | Use DTO or config object |
|
|
220
|
+
| Cyclomatic complexity | Max 10 | Split into smaller methods |
|
|
221
|
+
| Nesting depth | Max 3 | Early return pattern |
|
|
222
|
+
|
|
223
|
+
### Class Guidelines
|
|
224
|
+
|
|
225
|
+
| Metric | Limit | Action if exceeded |
|
|
226
|
+
| ------ | ----- | ------------------ |
|
|
227
|
+
| Public methods | Max 10 | Split class (SRP violation) |
|
|
228
|
+
| Dependencies | Max 5 | Facade or aggregate service |
|
|
229
|
+
| Lines per class | Max 500 | Extract sub-classes |
|
|
230
|
+
|
|
231
|
+
### Early Return Pattern
|
|
232
|
+
|
|
233
|
+
```php
|
|
234
|
+
// ❌ BAD: Deep nesting
|
|
235
|
+
public function process($user)
|
|
236
|
+
{
|
|
237
|
+
if ($user) {
|
|
238
|
+
if ($user->isActive()) {
|
|
239
|
+
if ($user->hasPermission('edit')) {
|
|
240
|
+
// do something
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// ✅ GOOD: Early returns
|
|
247
|
+
public function process($user)
|
|
248
|
+
{
|
|
249
|
+
if (!$user) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (!$user->isActive()) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (!$user->hasPermission('edit')) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// do something
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 🔵 Interface & Trait Naming
|
|
268
|
+
|
|
269
|
+
```php
|
|
270
|
+
// Interfaces: suffix with Interface
|
|
271
|
+
interface PaymentGatewayInterface
|
|
272
|
+
{
|
|
273
|
+
public function charge(int $amount): PaymentResult;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Traits: suffix with Trait (optional but recommended)
|
|
277
|
+
trait HasApiTokens
|
|
278
|
+
{
|
|
279
|
+
// ...
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Or descriptive name without suffix
|
|
283
|
+
trait Searchable
|
|
284
|
+
{
|
|
285
|
+
public function scopeSearch(Builder $query, string $term): Builder
|
|
286
|
+
{
|
|
287
|
+
// ...
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Quick Reference
|
|
295
|
+
|
|
296
|
+
| Category | Rule |
|
|
297
|
+
| -------- | ---- |
|
|
298
|
+
| **Strict** | `declare(strict_types=1)` at top |
|
|
299
|
+
| **Constructor** | Use property promotion with `readonly` |
|
|
300
|
+
| **Nullsafe** | `$obj?->prop?->value` instead of null checks |
|
|
301
|
+
| **Match** | Prefer `match` over `switch` |
|
|
302
|
+
| **Constants** | Use `App\Constants\*` classes |
|
|
303
|
+
| **Complexity** | Max 50 lines/method, 4 params, 10 complexity |
|
|
304
|
+
| **Nesting** | Max 3 levels, use early returns |
|
|
305
|
+
| **PHPDoc** | Document complex types and exceptions |
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "{{TYPESCRIPT_BASE}}/**/*.tsx"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# React + Ant Design Rules
|
|
7
|
+
|
|
8
|
+
## Core Patterns
|
|
9
|
+
|
|
10
|
+
### Service Layer (API calls)
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
// services/user.ts
|
|
14
|
+
export const userService = {
|
|
15
|
+
list: (params?: UserListParams) =>
|
|
16
|
+
api.get("/api/users", { params }).then(r => r.data),
|
|
17
|
+
create: (input: UserCreate) =>
|
|
18
|
+
api.post("/api/users", input).then(r => r.data.data),
|
|
19
|
+
};
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### TanStack Query
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
const { data, isLoading } = useQuery({
|
|
26
|
+
queryKey: queryKeys.users.list(filters),
|
|
27
|
+
queryFn: () => userService.list(filters),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const mutation = useMutation({
|
|
31
|
+
mutationFn: userService.create,
|
|
32
|
+
onSuccess: () => {
|
|
33
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.users.all });
|
|
34
|
+
message.success(t("messages.created"));
|
|
35
|
+
},
|
|
36
|
+
onError: (error) => form.setFields(getFormErrors(error)),
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## ⚠️ Enum Usage (CRITICAL)
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
// ✅ CORRECT - Import generated Enum
|
|
44
|
+
import { PostStatus, PostStatusValues } from "@omnify/enum/PostStatus";
|
|
45
|
+
|
|
46
|
+
// ✅ Use Enum values
|
|
47
|
+
if (status === PostStatus.Pending) { ... }
|
|
48
|
+
|
|
49
|
+
// ❌ WRONG - Inline union types
|
|
50
|
+
newFilter.status = status as "pending" | "approved";
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Ant Design Static Method Warning
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// ❌ Wrong - No context
|
|
57
|
+
import { message } from "antd";
|
|
58
|
+
message.success("Done");
|
|
59
|
+
|
|
60
|
+
// ✅ Correct - Use App.useApp()
|
|
61
|
+
const { message } = App.useApp();
|
|
62
|
+
message.success("Done");
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Full Documentation
|
|
66
|
+
|
|
67
|
+
See @.claude/omnify/guides/react/ for complete patterns.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "schemas/**/*.yaml"
|
|
4
|
+
- "schemas/**/*.yml"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Omnify Schema Rules
|
|
8
|
+
|
|
9
|
+
## Schema Workflow
|
|
10
|
+
|
|
11
|
+
1. Read @.claude/omnify/guides/omnify/schema-guide.md first
|
|
12
|
+
2. Create/edit YAML schema
|
|
13
|
+
3. Run `npx omnify generate`
|
|
14
|
+
4. Validate generated code
|
|
15
|
+
5. Run `php artisan migrate`
|
|
16
|
+
|
|
17
|
+
## Basic Template
|
|
18
|
+
|
|
19
|
+
```yaml
|
|
20
|
+
name: ModelName
|
|
21
|
+
kind: object
|
|
22
|
+
|
|
23
|
+
displayName:
|
|
24
|
+
ja: モデル名
|
|
25
|
+
en: Model Name
|
|
26
|
+
|
|
27
|
+
options:
|
|
28
|
+
timestamps: true
|
|
29
|
+
|
|
30
|
+
properties:
|
|
31
|
+
name:
|
|
32
|
+
type: String
|
|
33
|
+
length: 100
|
|
34
|
+
displayName:
|
|
35
|
+
ja: 名前
|
|
36
|
+
en: Name
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## ⚠️ CRITICAL: String Defaults
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
# ❌ WRONG - produces curly quotes
|
|
43
|
+
default: "'cloud'"
|
|
44
|
+
|
|
45
|
+
# ✅ CORRECT - just the value
|
|
46
|
+
default: cloud
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## ⚠️ CRITICAL: DB Functions NOT Allowed
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
# ❌ WRONG - DB functions
|
|
53
|
+
failed_at:
|
|
54
|
+
type: Timestamp
|
|
55
|
+
default: CURRENT_TIMESTAMP # ERROR!
|
|
56
|
+
|
|
57
|
+
# ✅ CORRECT - use useCurrent
|
|
58
|
+
failed_at:
|
|
59
|
+
type: Timestamp
|
|
60
|
+
useCurrent: true # = CURRENT_TIMESTAMP
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Property Types
|
|
64
|
+
|
|
65
|
+
| Type | SQL | TypeScript |
|
|
66
|
+
|------|-----|------------|
|
|
67
|
+
| String | VARCHAR | string |
|
|
68
|
+
| Text | TEXT | string |
|
|
69
|
+
| Int | INT | number |
|
|
70
|
+
| Boolean | BOOLEAN | boolean |
|
|
71
|
+
| DateTime | DATETIME | string |
|
|
72
|
+
|
|
73
|
+
## Relationships
|
|
74
|
+
|
|
75
|
+
| Relation | Description |
|
|
76
|
+
|----------|-------------|
|
|
77
|
+
| belongsTo | Foreign key on THIS table |
|
|
78
|
+
| hasMany | Foreign key on OTHER table |
|
|
79
|
+
| belongsToMany | Pivot table |
|
|
80
|
+
|
|
81
|
+
## Full Documentation
|
|
82
|
+
|
|
83
|
+
See @.claude/omnify/guides/omnify/schema-guide.md for complete syntax.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "{{LARAVEL_ROOT}}app/**/*.php"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Security Rules
|
|
7
|
+
|
|
8
|
+
> **Non-negotiable rules** for Laravel security. Violations = vulnerabilities.
|
|
9
|
+
|
|
10
|
+
## 🔴 Mass Assignment Vulnerability
|
|
11
|
+
|
|
12
|
+
**ALWAYS define `$fillable` in Models.**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// ❌ CRITICAL ERROR: No $fillable = mass assignment vulnerability
|
|
16
|
+
class User extends Model
|
|
17
|
+
{
|
|
18
|
+
// Missing $fillable!
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ❌ DANGEROUS: Using $request->all()
|
|
22
|
+
User::create($request->all()); // Attacker can set is_admin=true
|
|
23
|
+
|
|
24
|
+
// ✅ CORRECT: Define $fillable explicitly
|
|
25
|
+
class User extends Model
|
|
26
|
+
{
|
|
27
|
+
protected $fillable = [
|
|
28
|
+
'name_lastname',
|
|
29
|
+
'name_firstname',
|
|
30
|
+
'email',
|
|
31
|
+
'password',
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
// $guarded is alternative but $fillable is preferred (explicit)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ✅ CORRECT: Use validated data only
|
|
38
|
+
User::create($request->validated());
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
| Rule | Description |
|
|
42
|
+
| --------------------------------------------- | ------------------------------------------------------ |
|
|
43
|
+
| **Always define `$fillable`** | Explicitly list assignable fields |
|
|
44
|
+
| **Never use `$request->all()`** | Use `$request->validated()` or `$request->only([...])` |
|
|
45
|
+
| **Prefer `$fillable` over `$guarded`** | Whitelist is safer than blacklist |
|
|
46
|
+
| **Never put sensitive fields in `$fillable`** | `is_admin`, `role`, `balance` must NOT be fillable |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 🔴 SQL Injection Prevention
|
|
51
|
+
|
|
52
|
+
**NEVER use raw user input in queries.**
|
|
53
|
+
|
|
54
|
+
```php
|
|
55
|
+
// ❌ CRITICAL ERROR: SQL Injection vulnerability
|
|
56
|
+
$email = $request->input('email');
|
|
57
|
+
DB::select("SELECT * FROM users WHERE email = '$email'"); // DANGEROUS!
|
|
58
|
+
|
|
59
|
+
// ❌ DANGEROUS: String interpolation in whereRaw
|
|
60
|
+
User::whereRaw("email = '$email'")->get(); // DANGEROUS!
|
|
61
|
+
|
|
62
|
+
// ✅ CORRECT: Use parameter binding
|
|
63
|
+
DB::select("SELECT * FROM users WHERE email = ?", [$email]);
|
|
64
|
+
|
|
65
|
+
// ✅ CORRECT: Use Query Builder (auto-escapes)
|
|
66
|
+
User::where('email', $email)->get();
|
|
67
|
+
|
|
68
|
+
// ✅ CORRECT: Parameter binding in whereRaw
|
|
69
|
+
User::whereRaw('email = ?', [$email])->get();
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
| Rule | Description |
|
|
73
|
+
| -------------------------------- | ---------------------------------- |
|
|
74
|
+
| **Use Query Builder** | Eloquent auto-escapes values |
|
|
75
|
+
| **Use parameter binding** | `?` placeholders with array values |
|
|
76
|
+
| **Never concatenate user input** | No string interpolation in SQL |
|
|
77
|
+
| **Validate sort fields** | Whitelist allowed sort columns |
|
|
78
|
+
|
|
79
|
+
```php
|
|
80
|
+
// ✅ CORRECT: Whitelist sort fields to prevent SQL injection
|
|
81
|
+
$allowedSorts = ['id', 'name', 'email', 'created_at'];
|
|
82
|
+
$sortBy = in_array($request->sort_by, $allowedSorts)
|
|
83
|
+
? $request->sort_by
|
|
84
|
+
: 'id';
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 🔴 XSS Prevention
|
|
90
|
+
|
|
91
|
+
**Always escape output in Blade templates.**
|
|
92
|
+
|
|
93
|
+
```php
|
|
94
|
+
// ❌ DANGEROUS: Raw HTML output
|
|
95
|
+
{!! $user->bio !!} // XSS if bio contains <script>
|
|
96
|
+
|
|
97
|
+
// ✅ CORRECT: Escaped output (default)
|
|
98
|
+
{{ $user->bio }} // Auto-escapes HTML entities
|
|
99
|
+
|
|
100
|
+
// ✅ CORRECT: Only use {!! !!} for trusted HTML
|
|
101
|
+
{!! $trustedHtml !!} // Only for admin-generated content
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 🔴 CSRF Protection
|
|
107
|
+
|
|
108
|
+
**Never disable CSRF for web routes.**
|
|
109
|
+
|
|
110
|
+
```php
|
|
111
|
+
// ❌ DANGEROUS: Disabling CSRF
|
|
112
|
+
// In VerifyCsrfToken middleware
|
|
113
|
+
protected $except = ['*']; // NEVER do this!
|
|
114
|
+
|
|
115
|
+
// ✅ CORRECT: CSRF is enabled by default for web routes
|
|
116
|
+
// API routes use Sanctum tokens instead
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 🔴 Sensitive Data Exposure
|
|
122
|
+
|
|
123
|
+
**Hide sensitive fields from JSON responses.**
|
|
124
|
+
|
|
125
|
+
```php
|
|
126
|
+
// ❌ ERROR: Password exposed in API response
|
|
127
|
+
return response()->json($user); // Includes password!
|
|
128
|
+
|
|
129
|
+
// ✅ CORRECT: Use $hidden in Model
|
|
130
|
+
class User extends Model
|
|
131
|
+
{
|
|
132
|
+
protected $hidden = [
|
|
133
|
+
'password',
|
|
134
|
+
'remember_token',
|
|
135
|
+
'two_factor_secret',
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ✅ CORRECT: Use Resource to control output
|
|
140
|
+
class UserResource extends JsonResource
|
|
141
|
+
{
|
|
142
|
+
public function toArray($request): array
|
|
143
|
+
{
|
|
144
|
+
return [
|
|
145
|
+
'id' => $this->id,
|
|
146
|
+
'name' => $this->name,
|
|
147
|
+
// password NOT included
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Quick Reference
|
|
156
|
+
|
|
157
|
+
| ❌ Never Do | ✅ Always Do |
|
|
158
|
+
| ----------------------- | --------------------------------- |
|
|
159
|
+
| `$request->all()` | `$request->validated()` |
|
|
160
|
+
| Raw SQL with user input | Query Builder / parameter binding |
|
|
161
|
+
| Missing `$fillable` | Define `$fillable` explicitly |
|
|
162
|
+
| Missing `$hidden` | Hide sensitive fields |
|
|
163
|
+
| Disable CSRF | Keep CSRF enabled |
|
|
164
|
+
| `{!! $userInput !!}` | `{{ $userInput }}` |
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Ant Design deprecated props - check version before applying! v5.x and v6.x have different APIs"
|
|
3
|
+
globs: ["{{TYPESCRIPT_BASE}}/**/*.tsx", "{{TYPESCRIPT_BASE}}/**/*.ts"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Ant Design Deprecations
|
|
8
|
+
|
|
9
|
+
## ⚠️ Check Your Version First!
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Check package.json for antd version
|
|
13
|
+
grep '"antd"' package.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- **Ant Design 5.x**: Use `valueStyle`, `bodyStyle`, `headStyle`, `visible`
|
|
17
|
+
- **Ant Design 6.x**: Use `styles={{ ... }}`, `open` (semantic DOM API)
|
|
18
|
+
|
|
19
|
+
## Ant Design 5.x (Still Valid)
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// ✅ CORRECT for Ant Design 5.x
|
|
23
|
+
<Statistic value={100} valueStyle={{ color: 'green' }} />
|
|
24
|
+
<Card bodyStyle={{ padding: 0 }} headStyle={{ background: '#f5f5f5' }}>
|
|
25
|
+
<Modal visible={isOpen}>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Ant Design 6.x (Semantic DOM API)
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// ✅ CORRECT for Ant Design 6.x ONLY
|
|
32
|
+
<Statistic value={100} styles={{ content: { color: 'green' } }} />
|
|
33
|
+
<Card styles={{ body: { padding: 0 }, header: { background: '#f5f5f5' } }}>
|
|
34
|
+
<Modal open={isOpen}>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Deprecated in Both Versions
|
|
38
|
+
|
|
39
|
+
| Component | ❌ Deprecated | ✅ Use Instead |
|
|
40
|
+
| ------------ | -------------------------- | ----------------------- |
|
|
41
|
+
| Divider | `orientation` | `titlePlacement` |
|
|
42
|
+
| Modal/Drawer | `visible` | `open` (v5.0.0+) |
|
|
43
|
+
| Select | `dropdownMatchSelectWidth` | `popupMatchSelectWidth` |
|
|
44
|
+
| DatePicker | `dropdownClassName` | `popupClassName` |
|
|
45
|
+
|
|
46
|
+
### Semantic Keys by Component
|
|
47
|
+
|
|
48
|
+
| Component | Keys |
|
|
49
|
+
| --------- | -------------------------------------------------------- |
|
|
50
|
+
| Statistic | `root`, `header`, `title`, `prefix`, `content`, `suffix` |
|
|
51
|
+
| Card | `root`, `header`, `title`, `extra`, `body`, `actions` |
|
|
52
|
+
| Modal | `root`, `header`, `title`, `body`, `footer`, `mask` |
|
|
53
|
+
| Drawer | `root`, `header`, `title`, `body`, `footer`, `mask` |
|
|
54
|
+
|
|
55
|
+
### Pattern
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
<Component
|
|
59
|
+
styles={{ [semanticKey]: { /* CSSProperties */ } }}
|
|
60
|
+
classNames={{ [semanticKey]: 'my-class' }}
|
|
61
|
+
/>
|
|
62
|
+
```
|