Skip to content

feat: save AI diagnostics locally on each successful request#21

Merged
tassan merged 2 commits intomainfrom
copilot/save-ai-diagnostics-locally
Mar 5, 2026
Merged

feat: save AI diagnostics locally on each successful request#21
tassan merged 2 commits intomainfrom
copilot/save-ai-diagnostics-locally

Conversation

Copy link
Contributor

Copilot AI commented Mar 5, 2026

Every AI diagnostic generated by /api/diagnostico-ia needs to be persisted for later analysis and eventual migration to Google Drive or similar.

Changes

  • storage/diagnostics/ — new directory at project root (outside public/, never web-accessible). Tracked via .gitkeep; actual JSON files excluded from git.
  • .gitignore — adds /storage/diagnostics/*.json to keep saved diagnostics out of version control.
  • public/api/diagnostico-ia.php — after $parecer is validated, writes a timestamped JSON file containing created_at, sanitized input, and parecer. Best-effort: write failures are logged but never surface to the caller.

Saved file format

Filename: YYYY-MM-DD_HHmmss_<8-hex-random>.json

{
    "created_at": "2026-03-05T03:56:24+00:00",
    "input": {
        "nome": "João Silva",
        "negocio": "Clínica Odontológica ABC",
        "segmento": "saude",
        ...
    },
    "parecer": {
        "titulo": "...",
        "situacao_atual": "...",
        "gaps": [...],
        "urgencia": "alta"
    }
}

File uniqueness uses bin2hex(random_bytes(4)) rather than uniqid() for proper entropy.

Original prompt

This section details on the original issue you should resolve

<issue_title>Feature: Save AI diagnostics</issue_title>
<issue_description>We need to save every AI diagnostic made in the process.

At first we can save locally in the site, but we'll need to figure out how to properly save them in Google Drive or similar.</issue_description>

Comments on the Issue (you are @copilot in this section)


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Co-authored-by: tassan <7563760+tassan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add functionality to save AI diagnostics locally feat: save AI diagnostics locally on each successful request Mar 5, 2026
@tassan tassan requested a review from Copilot March 5, 2026 12:16
@tassan tassan marked this pull request as ready for review March 5, 2026 12:16
@tassan tassan merged commit b876e72 into main Mar 5, 2026
4 checks passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements best-effort local persistence of every successful AI diagnostic result, so data can later be migrated to Google Drive or a similar service. It adds a storage/diagnostics/ directory outside the web root, writes timestamped JSON files there after each successful AI response, and excludes those files from version control.

Changes:

  • Each validated AI diagnostic is serialized to a uniquely-named JSON file under storage/diagnostics/.
  • The storage/diagnostics/ directory is tracked via .gitkeep, with actual data files excluded by .gitignore.
  • Write failures are logged via error_log and never surfaced to the caller.

Reviewed changes

Copilot reviewed 1 out of 3 changed files in this pull request and generated 3 comments.

File Description
public/api/diagnostico-ia.php After building $parecer, writes a JSON record containing created_at, sanitized $input, and $parecer to storage/diagnostics/.
.gitignore Excludes *.json files inside /storage/diagnostics/ from version control.
storage/diagnostics/.gitkeep Ensures the storage directory is tracked in git while keeping it empty.

Comment on lines +238 to +240
$filename = date('Y-m-d_His') . '_' . bin2hex(random_bytes(4)) . '.json';
$record = json_encode(
['created_at' => date('c'), 'input' => $input, 'parecer' => $parecer],
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both date('Y-m-d_His') (used in the filename) and date('c') (used for created_at) depend on the PHP runtime's configured date.timezone. Since no timezone is set explicitly in the code or php.ini within the project, the output will reflect the server's system timezone rather than guaranteed UTC. The PR description example shows +00:00, implying UTC is assumed. Using date_create('now', timezone_open('UTC')) with date_format(), or simply calling date_default_timezone_set('UTC') before these calls, would make the timestamps deterministic across different hosting environments.

Suggested change
$filename = date('Y-m-d_His') . '_' . bin2hex(random_bytes(4)) . '.json';
$record = json_encode(
['created_at' => date('c'), 'input' => $input, 'parecer' => $parecer],
$nowUtc = new DateTimeImmutable('now', new DateTimeZone('UTC'));
$filename = $nowUtc->format('Y-m-d_His') . '_' . bin2hex(random_bytes(4)) . '.json';
$record = json_encode(
['created_at' => $nowUtc->format(DATE_ATOM), 'input' => $input, 'parecer' => $parecer],

Copilot uses AI. Check for mistakes.
$written = file_put_contents($storageDir . '/' . $filename, $record . "\n");
if ($written === false) {
error_log('Failed to write diagnostic file: ' . $storageDir . '/' . $filename);
}
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When json_encode() returns false (e.g., due to malformed UTF-8 sequences from AI response fields being embedded in $parecer), the failure is silently ignored with no error_log() call. This makes it hard to diagnose encoding issues in production. An error_log should be added for this failure path, similar to how the file-write failure is handled at line 246.

Suggested change
}
}
} else {
error_log('Failed to json_encode diagnostic record: ' . json_last_error_msg());

Copilot uses AI. Check for mistakes.
Comment on lines +234 to +240
@mkdir($storageDir, 0755, true);
}

if (is_dir($storageDir) && is_writable($storageDir)) {
$filename = date('Y-m-d_His') . '_' . bin2hex(random_bytes(4)) . '.json';
$record = json_encode(
['created_at' => date('c'), 'input' => $input, 'parecer' => $parecer],
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The $input array persisted in the JSON file includes email and telefone — personally identifiable information (PII). These files are written to disk at storage/diagnostics/ in plain text with no access controls beyond filesystem permissions. In a Docker setup (as per docker-compose.yml) the entire project root is bind-mounted and the process runs as www-data. Consider whether saving PII locally aligns with applicable data-protection obligations (e.g. LGPD in Brazil), and whether the storage directory should have tighter permissions (e.g., 0700) or PII fields should be excluded from the stored record.

Suggested change
@mkdir($storageDir, 0755, true);
}
if (is_dir($storageDir) && is_writable($storageDir)) {
$filename = date('Y-m-d_His') . '_' . bin2hex(random_bytes(4)) . '.json';
$record = json_encode(
['created_at' => date('c'), 'input' => $input, 'parecer' => $parecer],
// Restrictive permissions: only the web server user can read/write
@mkdir($storageDir, 0700, true);
}
if (is_dir($storageDir) && is_writable($storageDir)) {
$filename = date('Y-m-d_His') . '_' . bin2hex(random_bytes(4)) . '.json';
// Avoid persisting PII (e.g. email, telefone) in diagnostics storage
$inputForStorage = $input;
unset($inputForStorage['email'], $inputForStorage['telefone']);
$record = json_encode(
['created_at' => date('c'), 'input' => $inputForStorage, 'parecer' => $parecer],

Copilot uses AI. Check for mistakes.
@github-actions github-actions bot deleted the copilot/save-ai-diagnostics-locally branch March 6, 2026 03:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Save AI diagnostics

3 participants