feat: implement AI styling foundation and billing scope rework
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-02-06 20:01:58 +01:00
parent df00deb0df
commit 36bed12ff9
80 changed files with 8944 additions and 49 deletions

View File

@@ -171,6 +171,46 @@ class AppServiceProvider extends ServiceProvider
return Limit::perMinute(20)->by('tenant-auth:'.($request->ip() ?? 'unknown'));
});
RateLimiter::for('ai-edit-guest-submit', function (Request $request) {
$token = (string) $request->route('token');
$deviceId = trim((string) $request->header('X-Device-Id', ''));
$scope = $deviceId !== '' ? 'device:'.$deviceId : 'ip:'.($request->ip() ?? 'unknown');
$key = 'ai-edit-guest-submit:'.$token.':'.$scope;
return [
Limit::perMinute(max(1, (int) config('ai-editing.abuse.guest_submit_per_minute', 8)))->by($key),
Limit::perHour(max(1, (int) config('ai-editing.abuse.guest_submit_per_hour', 40)))->by($key),
];
});
RateLimiter::for('ai-edit-guest-status', function (Request $request) {
$token = (string) $request->route('token');
$deviceId = trim((string) $request->header('X-Device-Id', ''));
$scope = $deviceId !== '' ? 'device:'.$deviceId : 'ip:'.($request->ip() ?? 'unknown');
$key = 'ai-edit-guest-status:'.$token.':'.$scope;
return Limit::perMinute(max(1, (int) config('ai-editing.abuse.guest_status_per_minute', 60)))->by($key);
});
RateLimiter::for('ai-edit-tenant-submit', function (Request $request) {
$tenantId = (string) ($request->attributes->get('tenant_id') ?? 'tenant');
$userId = (string) ($request->user()?->id ?? 'guest');
$key = 'ai-edit-tenant-submit:'.$tenantId.':'.$userId;
return [
Limit::perMinute(max(1, (int) config('ai-editing.abuse.tenant_submit_per_minute', 30)))->by($key),
Limit::perHour(max(1, (int) config('ai-editing.abuse.tenant_submit_per_hour', 240)))->by($key),
];
});
RateLimiter::for('ai-edit-tenant-status', function (Request $request) {
$tenantId = (string) ($request->attributes->get('tenant_id') ?? 'tenant');
$userId = (string) ($request->user()?->id ?? 'guest');
$key = 'ai-edit-tenant-status:'.$tenantId.':'.$userId;
return Limit::perMinute(max(1, (int) config('ai-editing.abuse.tenant_status_per_minute', 120)))->by($key);
});
RateLimiter::for('coupon-preview', function (Request $request) {
$code = strtoupper((string) $request->input('code'));
$identifier = ($request->ip() ?? 'unknown').($code ? ':'.$code : '');