Fix API correctness: external API stub/collision, recurring dates, CSV, audit

- create_ticket_api.php: remove the wrong CREATE TABLE stub that broke a
  fresh DB; generate collision-safe ticket_ids so a genuine id collision
  isn't misreported as a duplicate and a hw alert dropped; stop leaking
  raw DB errors; correct a reopen comment that falsely claimed refreshed
  sensor data
- manage_recurring.php: fix next-run so create/edit no longer skips the
  current period (monthly day-of-month this month, daily today if time
  not passed, correct ISO weekday, month-length clamp); only recompute
  on schedule changes to avoid double-fire
- export_tickets.php, audit_log.php: neutralize CSV formula injection
- revoke_api_key.php, generate_api_key.php: correct HTTP status codes and
  stop the catch clobbering specific 4xx codes
- health.php: stop leaking PHP version / extension names / paths to
  unauthenticated callers
- watch_ticket.php: define $data before use
- manage_templates/recurring/custom_fields: add audit logging for CRUD;
  add recurring_ticket + custom_field to the audit entity whitelist

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 12:26:39 -04:00
co-authored by Claude Opus 4.8
parent 327c225ded
commit d11cb989bf
11 changed files with 322 additions and 68 deletions
+17 -1
View File
@@ -15,6 +15,22 @@ error_reporting(E_ALL);
require_once dirname(__DIR__) . '/middleware/RateLimitMiddleware.php';
RateLimitMiddleware::apply('api');
/**
* Neutralize CSV/formula injection: prefix a leading apostrophe to any cell that
* a spreadsheet (Excel/Sheets) would otherwise evaluate as a formula.
*
* @param mixed $value
* @return string
*/
function exportCsvSafeCell($value): string
{
$value = (string)$value;
if ($value !== '' && in_array($value[0], ['=', '+', '-', '@', "\t", "\r"], true)) {
return "'" . $value;
}
return $value;
}
try {
// Include required files
require_once dirname(__DIR__) . '/config/config.php';
@@ -124,7 +140,7 @@ try {
$ticket['updated_at'],
$ticket['description']
];
fputcsv($output, $row);
fputcsv($output, array_map('exportCsvSafeCell', $row));
}
fclose($output);