fix(docker-watcher): address final review findings

Security:
- Move config export behind auth middleware
- Validate OIDC callback token before storing in localStorage
- Use constant-time comparison for webhook secret
- Encrypt OIDC client secret at rest (like registry tokens)

Performance:
- Make TriggerDeploy async from HTTP handlers (return deploy ID
  immediately, run pipeline in background goroutine)

Robustness:
- Wrap api.ts res.json() in try/catch for non-JSON responses

i18n:
- Replace ~20 hardcoded English validation messages with $t() calls
- Localize ConfirmDialog cancel button, InstanceCard confirm titles,
  ProjectCard instance/instances pluralization
- Add validation keys to both en.json and ru.json
This commit is contained in:
2026-03-28 00:14:53 +03:00
parent a3aa5912d9
commit 1f81ca9eb0
17 changed files with 178 additions and 40 deletions
+6 -6
View File
@@ -22,24 +22,24 @@
let errors = $state<Record<string, string>>({});
function validateImageUrl(url: string): string {
if (!url.trim()) return 'Image URL is required';
if (!url.trim()) return $t('validation.required', { field: 'Image URL' });
if (!/^[a-zA-Z0-9._\-/]+:[a-zA-Z0-9._\-]+$/.test(url.trim())) {
return 'Invalid image URL format (e.g., registry.example.com/org/app:tag)';
return $t('validation.invalidUrl');
}
return '';
}
function validatePort(value: string): string {
if (!value.trim()) return 'Port is required';
if (!value.trim()) return $t('validation.required', { field: 'Port' });
const num = parseInt(value, 10);
if (isNaN(num) || num < 1 || num > 65535) return 'Port must be between 1 and 65535';
if (isNaN(num) || num < 1 || num > 65535) return $t('validation.invalidPort');
return '';
}
function validateProjectName(value: string): string {
if (!value.trim()) return 'Project name is required';
if (!value.trim()) return $t('validation.required', { field: 'Project name' });
if (value.trim().length > 1 && !/^[a-z0-9][a-z0-9\-]*[a-z0-9]$/.test(value.trim())) {
return 'Must be lowercase alphanumeric with hyphens (e.g., my-app)';
return $t('validation.invalidProjectName');
}
return '';
}