fix(instanda): rate limiting, UTC timestamps, and close silent-failure paths
- F-06: throttle the public create per IP (20/h) and per email (5/h) before the paid API call and the PII write. - F-11: wrap the create path in try/catch - on an unexpected error fail closed for that submission (no quote-less entry), alert admins, keep the form working. - F-14: abort the StartQuote when the write-ahead insert fails (no unaudited call); fire the failure alert even when storage is disabled (build an in-memory tx). - F-10/F-17: treat a 2xx with a missing/empty quoteRef as ambiguous (possible_duplicate=1), not a hard failure - a quote may exist. - F-07: write created_at/delivered_at/event timestamps in UTC to match the gmdate() retention/dedupe cutoffs; display in site-local via get_date_from_gmt. - F-09: log (no silent return) when async record_feed_result cannot resolve a delivered transaction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -137,7 +137,7 @@ final class Transaction_Store {
|
||||
/** Write-ahead insert. Returns the new row id (0 on failure). */
|
||||
public function create_pending(Transaction $t): int {
|
||||
global $wpdb;
|
||||
$now = current_time('mysql');
|
||||
$now = current_time('mysql', true); // UTC - matches the gmdate() retention/dedupe cutoffs
|
||||
$t->event_log[] = self::event('Write-ahead record created (status: pending)');
|
||||
|
||||
$ok = $wpdb->insert(self::table_name(), [
|
||||
@@ -159,14 +159,14 @@ final class Transaction_Store {
|
||||
}
|
||||
|
||||
public function mark_success(int $id, string $quote_ref, ?string $quote_url, ?int $http_status): void {
|
||||
$delivered = current_time('mysql');
|
||||
$delivered = current_time('mysql', true); // UTC
|
||||
$this->update($id, [
|
||||
'status' => Tx_Status::Delivered->value,
|
||||
'quote_ref' => $quote_ref,
|
||||
'quote_url' => $quote_url,
|
||||
'http_status' => $http_status,
|
||||
'delivered_at' => $delivered,
|
||||
'expiry' => $this->compute_expiry($delivered),
|
||||
'expiry' => $this->compute_expiry(),
|
||||
], 'Delivered - quoteRef ' . $quote_ref);
|
||||
}
|
||||
|
||||
@@ -375,14 +375,14 @@ final class Transaction_Store {
|
||||
$wpdb->update(self::table_name(), $data, ['id' => $id]);
|
||||
}
|
||||
|
||||
private function compute_expiry(string $delivered_at): string {
|
||||
/** Expiry = now + retention window, in UTC (delivered_at is written at ~the same instant). */
|
||||
private function compute_expiry(): string {
|
||||
$days = (int) get_option('espinstanda_retention_days', 7);
|
||||
$ts = strtotime($delivered_at) ?: time();
|
||||
return gmdate('Y-m-d H:i:s', $ts + ($days * DAY_IN_SECONDS));
|
||||
return gmdate('Y-m-d H:i:s', time() + ($days * DAY_IN_SECONDS));
|
||||
}
|
||||
|
||||
/** @return array{ts:string,level:string,message:string} */
|
||||
private static function event(string $message, string $level = 'info'): array {
|
||||
return ['ts' => current_time('mysql'), 'level' => $level, 'message' => Logger::redact($message)];
|
||||
return ['ts' => current_time('mysql', true), 'level' => $level, 'message' => Logger::redact($message)];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user