Commit Graph

549 Commits

Author SHA1 Message Date
gitea-actions[bot]
95a63e18bf chore: update CHANGELOG.md for v0.3.9 [skip ci] 2026-06-01 01:55:47 +00:00
ba94f446c1 Merge pull request 'fix(security): expand Password PII patterns to catch pass: and natural language forms' (#60) from fix/pii-detection-bypass into master
All checks were successful
Auto Tag / autotag (push) Successful in 6s
Auto Tag / wiki-sync (push) Successful in 7s
Test / rust-fmt-check (push) Successful in 1m25s
Auto Tag / changelog (push) Successful in 1m34s
Test / frontend-tests (push) Successful in 1m42s
Test / frontend-typecheck (push) Successful in 1m43s
Auto Tag / build-macos-arm64 (push) Successful in 2m34s
Test / rust-clippy (push) Successful in 3m26s
Test / rust-tests (push) Successful in 5m4s
Auto Tag / build-linux-amd64 (push) Successful in 8m50s
Auto Tag / build-windows-amd64 (push) Successful in 10m41s
Auto Tag / build-linux-arm64 (push) Successful in 11m1s
Reviewed-on: #60
2026-06-01 01:54:13 +00:00
Shaun Arman
fbd6aab7fe fix(security): expand Password PII patterns; add regression tests
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m20s
Test / frontend-typecheck (pull_request) Successful in 1m37s
Test / frontend-tests (pull_request) Successful in 1m35s
Test / rust-clippy (pull_request) Successful in 3m11s
PR Review Automation / review (pull_request) Successful in 4m22s
Test / rust-tests (pull_request) Successful in 4m28s
Two credential patterns were missing from the PiiDetector, confirmed
by live audit log showing was_pii_redacted: false with plaintext creds:

1. Abbreviated key form (pass: abc123!!): the pattern only matched
   password|passwd|pwd. Added pass, passphrase, secret with a word
   boundary to prevent substring false positives (bypass:, compass:).

2. Natural language form (Is the password password123 good): added a
   second Password sub-pattern for keyword-adjacent values without a
   key separator. Value must contain a digit or special char to avoid
   flagging plain words (password strength, password policy).

5 new regression tests added. 233/233 Rust tests pass.
2026-05-31 20:47:59 -05:00
gitea-actions[bot]
2f3b1b826c chore: update CHANGELOG.md for v0.3.8 [skip ci] 2026-06-01 01:21:56 +00:00
19645c06e2 Merge pull request 'fix(security): block PII in chat attachments and typed messages' (#59) from fix/pii-detection-bypass into master
All checks were successful
Auto Tag / autotag (push) Successful in 7s
Auto Tag / wiki-sync (push) Successful in 8s
Test / rust-fmt-check (push) Successful in 1m20s
Test / frontend-typecheck (push) Successful in 1m29s
Test / frontend-tests (push) Successful in 1m31s
Auto Tag / changelog (push) Successful in 1m29s
Auto Tag / build-macos-arm64 (push) Successful in 2m41s
Test / rust-clippy (push) Successful in 3m28s
Test / rust-tests (push) Successful in 5m33s
Auto Tag / build-linux-amd64 (push) Successful in 8m55s
Auto Tag / build-windows-amd64 (push) Successful in 10m41s
Auto Tag / build-linux-arm64 (push) Successful in 10m46s
Reviewed-on: #59
2026-06-01 01:20:25 +00:00
Shaun Arman
249d20bf85 fix: audit PII redaction metadata, safe bubble update, update ticket
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m54s
Test / frontend-typecheck (pull_request) Successful in 2m6s
Test / frontend-tests (pull_request) Successful in 2m5s
Test / rust-clippy (pull_request) Successful in 3m59s
PR Review Automation / review (pull_request) Successful in 4m10s
Test / rust-tests (pull_request) Successful in 5m15s
Add was_pii_redacted and pii_types_redacted to the ai_chat audit log
entry. Both are tracked through the full_message build block (typed
message + attachments) so any redaction that occurs is always
reflected in the compliance record.

Fix response.user_message + suffix potentially yielding 'undefined...'
when user_message is absent. Now unconditionally calls
updateMessageContent with (response.user_message ?? message) + suffix,
so the bubble always shows a valid string regardless of backend build.

Update TICKET-pii-bypass-chat-attachments.md to reflect the final
auto-redact design (not block/warn) so automated review comparisons
against the ticket stop flagging design decisions as defects.
2026-05-31 20:14:23 -05:00
Shaun Arman
631221dbf1 fix(security): full-content PII scan, clippy, IPC null fix, scan size cap
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m40s
Test / frontend-typecheck (pull_request) Successful in 1m48s
Test / frontend-tests (pull_request) Successful in 1m43s
Test / rust-clippy (pull_request) Successful in 3m17s
Test / rust-tests (pull_request) Successful in 4m33s
PR Review Automation / review (pull_request) Successful in 5m0s
Remove frontend detectPiiCmd pre-scan loop — backend is sole redaction
authority; bubble update via response.user_message covers user feedback.

Detect PII on full file content before truncating. Previous order
(truncate to 8000 bytes then scan) could miss PII straddling the
boundary. Now: read full content, scan, redact, then truncate to
EMBED_LIMIT (8000 bytes) at a valid UTF-8 char boundary.

logFileIds IPC: pass undefined (not null) for empty array so Tauri
serialises it correctly to Rust Option::None.

Add MAX_TEXT_SCAN_BYTES (32 KB) guard in scan_text_for_pii to prevent
unbounded regex evaluation on oversized payloads.

Fix clippy uninlined_format_args in ai.rs.
2026-05-31 20:01:07 -05:00
Shaun Arman
e9c576f606 fix(security): frontend attachment scan notice, bubble redaction update, fmt fix
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 2m3s
Test / frontend-tests (pull_request) Successful in 1m56s
Test / frontend-typecheck (pull_request) Successful in 1m58s
Test / rust-clippy (pull_request) Failing after 3m0s
Test / rust-tests (pull_request) Successful in 4m22s
PR Review Automation / review (pull_request) Successful in 4m35s
Addresses three findings from the third automated review:

[BLOCKER] No frontend PII pre-check on attachments.
Added detectPiiCmd call for each logFileId before chatMessageCmd.
PII is not blocked (per explicit product decision: auto-redact and
send) but the user now sees a non-blocking amber notice listing
each file and the PII types that will be auto-redacted. Backend
remains the authoritative redaction layer.

[WARNING 2] Chat bubble showed original PII-laden message even though
only the redacted form was sent to AI.
Added updateMessageContent to sessionStore. After chatMessageCmd
returns, if response.user_message is set the user bubble is updated
to reflect what was actually stored in the DB, so the UI is
consistent with the audit log.

CI fix: cargo fmt changes to analysis.rs were not staged in the prior
commit. Committed here — fmt check now passes cleanly.
2026-05-31 19:49:21 -05:00
Shaun Arman
a04d6fc8f5 fix(security): backend-only PII redaction; fix fmt CI failure
Some checks failed
Test / frontend-typecheck (pull_request) Successful in 1m52s
Test / frontend-tests (pull_request) Successful in 1m51s
Test / rust-fmt-check (pull_request) Failing after 1m58s
Test / rust-clippy (pull_request) Failing after 3m4s
Test / rust-tests (pull_request) Successful in 4m31s
PR Review Automation / review (pull_request) Successful in 4m43s
Resolves all three findings from the second automated review and
fixes the cargo fmt --check CI failure (formatting drift in analysis.rs
from a prior merge).

[BLOCKER 1 + BLOCKER 2 + WARNING]
Frontend no longer performs any PII scanning or redaction. All three
concerns stemmed from the same root cause: outMessage was derived
on the frontend and used for display, DB storage (via lastUserMsgRef
and the chat bubble), and the AI payload — causing the original message
to be silently replaced before the backend received it.

Fix: frontend sends the original message verbatim. Backend is now the
sole authority. chat_message auto-redacts the typed message text using
PiiDetector + apply_redactions() before building the full payload, logs
the PII types via tracing::warn, and stores only the redacted form in
ai_messages and the audit log. The redacted form is returned to the
caller as ChatResponse.user_message (Option<String>, absent from direct
provider calls).

Frontend uses message (original) for the chat bubble and
lastUserMsgRef — resolution steps show natural language, not
[Password] tokens. The AI and DB see only the redacted version.

CI fix: cargo fmt applied to analysis.rs; all format checks now pass.
2026-05-31 19:36:44 -05:00
Shaun Arman
f05b954250 fix(security): address PR review — move attachment handling to backend, auto-redact PII
Some checks failed
Test / rust-fmt-check (pull_request) Failing after 1m25s
Test / frontend-typecheck (pull_request) Successful in 1m37s
Test / frontend-tests (pull_request) Successful in 1m36s
Test / rust-clippy (pull_request) Failing after 3m18s
PR Review Automation / review (pull_request) Successful in 4m19s
Test / rust-tests (pull_request) Successful in 4m30s
Resolves all four findings from the automated review:

[BLOCKER 1] Attachment PII scan error path left pendingFiles intact,
allowing retry with stale file references. Fix: file content is no
longer held in frontend state at all — PendingFile drops the content
field entirely. logFileIds are captured before setPendingFiles([]) and
passed directly to the backend.

[BLOCKER 2] Raw file content stored in PendingFile.content created a
UI-visible PII surface and a data-residency risk. Fix: frontend never
reads or stores file content. The backend loads file data from disk,
auto-redacts PII in-memory using pii::apply_redactions(), and embeds
the clean text into the AI message. No PII ever touches the frontend.

[WARNING 1] String-based attachment header parsing was fragile and
bypassable. Fix: parsing is gone — backend identifies attachments by
log_file_id, reads them directly from the DB/disk path, and applies
redaction at that level.

[WARNING 2] Error message disclosed PII type list to the caller. Fix:
PII types are logged via tracing::warn only; no type details in the
user-facing error or API response.

Additionally: typed chat messages are now auto-redacted rather than
blocked. scanTextForPiiCmd runs on the typed text; detected spans are
replaced in reverse-offset order before the message is sent to the AI
and stored in the DB. The user sees the redacted form in their chat
bubble.

Architecture:
- chat_message now accepts log_file_ids: Option<Vec<String>>
- Backend reads file → detects PII → redacts in memory → embeds
- Frontend: no readTextFile, no content field, no frontend PII gate
2026-05-31 19:20:46 -05:00
Shaun Arman
cd26801a39 fix(security): block PII in chat attachments and typed messages
Some checks failed
Test / rust-fmt-check (pull_request) Failing after 1m31s
Test / frontend-tests (pull_request) Successful in 1m34s
Test / frontend-typecheck (pull_request) Successful in 1m36s
Test / rust-clippy (pull_request) Successful in 3m5s
PR Review Automation / review (pull_request) Successful in 4m31s
Test / rust-tests (pull_request) Successful in 4m27s
File attachments were embedded into AI messages without any PII
scanning, allowing credentials, tokens, and other sensitive data
to be forwarded to AI providers in plaintext.

Typed chat messages had the same gap: a user could type a password
or API key directly and it would be sent unscanned.

Changes:
- chat_message (Rust): defence-in-depth scan of all attachment body
  content (between --- Attached: markers); hard rejects if PII found
- detect_pii (Rust): fix return type from pii::PiiDetectionResult
  (spans/original_text) to db::models::PiiDetectionResult
  (detections/total_pii_found) to match the TypeScript contract; the
  LogUpload PII review workflow was receiving undefined for detections
- scan_text_for_pii (Rust): new command — scans arbitrary text for PII
  without creating DB records; used for typed message warnings
- Triage/index.tsx: PendingFile now carries logFileId; handleSend gates
  each text attachment through detectPiiCmd (hard block on PII found);
  typed message text scanned via scanTextForPiiCmd with a one-time
  warning — second send of same message proceeds as acknowledgment
2026-05-31 19:05:51 -05:00
gitea-actions[bot]
fb57c629a9 chore: update CHANGELOG.md for v0.3.7 [skip ci] 2026-05-31 23:14:06 +00:00
0f1f4fcb92 Merge pull request 'feat: attachment DB storage and cross-incident recall' (#58) from feature/attachment-db-storage-recall into master
Some checks failed
Auto Tag / autotag (push) Successful in 7s
Auto Tag / wiki-sync (push) Successful in 7s
Test / rust-fmt-check (push) Failing after 1m24s
Test / frontend-typecheck (push) Successful in 1m43s
Auto Tag / changelog (push) Successful in 1m31s
Test / frontend-tests (push) Successful in 1m42s
Auto Tag / build-macos-arm64 (push) Successful in 2m57s
Test / rust-clippy (push) Successful in 3m51s
Test / rust-tests (push) Successful in 5m17s
Auto Tag / build-linux-amd64 (push) Successful in 10m3s
Auto Tag / build-windows-amd64 (push) Successful in 11m35s
Auto Tag / build-linux-arm64 (push) Successful in 11m34s
Reviewed-on: #58
2026-05-31 23:12:38 +00:00
Shaun Arman
911b6f591b fix: address PR review findings — compress errors, size guard, modal error display
Some checks failed
Test / rust-fmt-check (pull_request) Failing after 1m43s
Test / frontend-typecheck (pull_request) Successful in 2m8s
Test / frontend-tests (pull_request) Successful in 2m7s
Test / rust-clippy (pull_request) Successful in 3m17s
Test / rust-tests (pull_request) Successful in 4m32s
PR Review Automation / review (pull_request) Successful in 5m25s
- compress_text now returns Result<Vec<u8>, String>; callers propagate
  the error instead of silently storing empty BLOB on gzip failure
- upload_image_attachment_by_content and upload_paste_image now validate
  decoded byte length against MAX_IMAGE_FILE_BYTES before DB storage,
  closing the size-bypass gap that existed for base64 content uploads
- Image View modal in AttachmentsTab now surfaces the error string when
  get_image_attachment_data fails, replacing the opaque "could not be
  loaded" message with actionable diagnostic text

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 18:06:07 -05:00
Shaun Arman
1b36ebfb3d feat: attachment DB storage and cross-incident recall
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m35s
Test / frontend-tests (pull_request) Successful in 1m41s
Test / frontend-typecheck (pull_request) Successful in 1m43s
Test / rust-clippy (pull_request) Successful in 3m10s
Test / rust-tests (pull_request) Successful in 4m39s
PR Review Automation / review (pull_request) Successful in 4m58s
Store compressed log content and raw image bytes in SQLite so attachments
are self-contained regardless of source file availability on disk.

DB (migrations 020-022):
- log_files.content_compressed BLOB — gzip-compressed extracted text
- image_attachments.image_data BLOB — raw image bytes
- Views v_log_files_with_issue and v_image_attachments_with_issue for
  cross-incident queries with joined issue title

Rust backend:
- compress_text / decompress_text helpers (flate2 rust_backend / miniz_oxide)
  with 100 MB decompression-bomb guard
- upload_log_file*, upload_log_file_by_content store content_compressed
- upload_image_attachment*, upload_paste_image store image_data
- New commands: get_log_file_content, list_all_log_files (analysis.rs)
- New commands: get_image_attachment_data, list_all_image_attachments (image.rs)
- All commands fall back to file_path for pre-migration records

Frontend:
- LogFileSummary, ImageAttachmentSummary types in tauriCommands.ts
- attachmentStore (Zustand) — loadAttachments, searchAttachments
- History page: Issues tab (existing) + Attachments tab (new)
  with log/image tables, search bar, View modals, lazy thumbnails

Tests: 227 Rust (+16 new), 103 frontend (+9 new), tsc clean, clippy clean

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 17:55:47 -05:00
gitea-actions[bot]
f496748cd3 chore: update CHANGELOG.md for v0.3.6 [skip ci] 2026-05-31 21:45:02 +00:00
3fe06ce498 Merge pull request 'fix(ci): push detached HEAD to master using HEAD:master refspec' (#57) from fix/auto-tag-push-master into master
All checks were successful
Auto Tag / autotag (push) Successful in 7s
Auto Tag / wiki-sync (push) Successful in 6s
Test / rust-fmt-check (push) Successful in 1m36s
Test / frontend-tests (push) Successful in 2m14s
Test / frontend-typecheck (push) Successful in 2m15s
Auto Tag / changelog (push) Successful in 2m14s
Auto Tag / build-macos-arm64 (push) Successful in 3m9s
Test / rust-clippy (push) Successful in 4m58s
Test / rust-tests (push) Successful in 6m24s
Auto Tag / build-linux-amd64 (push) Successful in 8m52s
Auto Tag / build-windows-amd64 (push) Successful in 10m51s
Auto Tag / build-linux-arm64 (push) Successful in 11m1s
Reviewed-on: #57
2026-05-31 21:43:18 +00:00
Shaun Arman
34a69620f5 fix(ci): consolidate all auto-tag changelog fixes
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m25s
Test / frontend-typecheck (pull_request) Successful in 1m53s
Test / frontend-tests (pull_request) Successful in 1m53s
Test / rust-clippy (pull_request) Successful in 3m12s
PR Review Automation / review (pull_request) Successful in 4m24s
Test / rust-tests (pull_request) Successful in 4m37s
Three issues addressed together:

1. Race condition (was PR #56): changelog job now CREATES the Gitea
   release rather than assuming build jobs have already created it.
   Build jobs continue to use create-or-skip + upload unchanged.

2. Detached HEAD push: 'git push origin master' fails when HEAD is
   detached (no local branch named master). Changed to 'HEAD:master'.

3. git-cliff tag guard: verify tag is present locally before running
   git-cliff, to fail fast with a clear message rather than silently
   generating a wrong changelog.

4. git commit idiom: replaced 'git commit || echo' (swallows all
   non-zero exit codes including real failures) with an explicit
   'git diff --staged --quiet' guard so set -euo pipefail is not
   undermined.
2026-05-31 16:38:02 -05:00
Shaun Arman
f90c76911a fix(ci): push detached HEAD to master using HEAD:master refspec
The changelog job checks out a specific SHA (detached HEAD) then
commits CHANGELOG.md and tries to push with 'git push origin master'.
Since there is no local branch named 'master', git rejects the push
with 'src refspec master does not match any'.

Fix: use 'git push origin HEAD:master' which explicitly maps the
current detached HEAD to the remote master branch regardless of
local branch state.
2026-05-31 16:37:25 -05:00
8eccea96ec Merge pull request 'fix(ci): changelog job creates release, eliminating race with build jobs' (#56) from fix/auto-tag-changelog-race into master
Some checks failed
Auto Tag / autotag (push) Successful in 6s
Auto Tag / wiki-sync (push) Successful in 7s
Test / rust-fmt-check (push) Successful in 1m46s
Test / frontend-typecheck (push) Successful in 1m43s
Test / frontend-tests (push) Successful in 2m21s
Auto Tag / changelog (push) Failing after 2m20s
Auto Tag / build-macos-arm64 (push) Successful in 2m36s
Test / rust-clippy (push) Successful in 4m2s
Test / rust-tests (push) Successful in 5m43s
Auto Tag / build-linux-amd64 (push) Successful in 10m42s
Auto Tag / build-linux-arm64 (push) Successful in 13m6s
Auto Tag / build-windows-amd64 (push) Successful in 13m37s
Reviewed-on: #56
2026-05-31 21:13:11 +00:00
Shaun Arman
7ee4f58bfd fix(ci): verify tag exists locally before running git-cliff
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m42s
Test / rust-clippy (pull_request) Successful in 3m31s
Test / frontend-typecheck (pull_request) Successful in 2m40s
Test / frontend-tests (pull_request) Successful in 1m54s
Test / rust-tests (pull_request) Successful in 4m23s
PR Review Automation / review (pull_request) Successful in 6m15s
Addresses the review warning: git rev-parse confirms the tag is
present in the local repo after git fetch --tags before git-cliff
or git tag --sort= runs against it. Fails fast with a clear error
if the tag is missing rather than silently generating an incomplete
changelog.
2026-05-31 16:05:18 -05:00
Shaun Arman
cc99aa815b fix(ci): changelog job creates release to avoid race with build jobs
Some checks failed
Test / rust-fmt-check (pull_request) Waiting to run
PR Review Automation / review (pull_request) Successful in 4m38s
Test / frontend-typecheck (pull_request) Successful in 1m22s
Test / rust-clippy (pull_request) Successful in 6m12s
Test / frontend-tests (pull_request) Successful in 1m13s
Test / rust-tests (pull_request) Has been cancelled
The changelog and build-* jobs all fan out from autotag in parallel.
Build jobs create the Gitea release with 'curl ... || true', but the
changelog job was trying to GET the release before any build job had
run, reliably failing with 'Could not find release for tag vX.Y.Z'.

Fix: changelog job owns release creation. It creates the release with
the git-cliff body if it does not exist, or patches the body if a
prior run already created it. Build jobs continue using their existing
create-or-skip + upload pattern unchanged.
2026-05-31 15:57:26 -05:00
d3dfa41d83 Merge pull request 'fix: safe uploads, AI history continuity, deep search, sudo credentials' (#55) from fix/safe-uploads-history-search-sudo into master
Some checks failed
Auto Tag / autotag (push) Successful in 7s
Auto Tag / wiki-sync (push) Successful in 6s
Test / rust-fmt-check (push) Successful in 1m18s
Test / frontend-tests (push) Successful in 1m27s
Test / frontend-typecheck (push) Successful in 1m30s
Auto Tag / changelog (push) Failing after 1m27s
Auto Tag / build-macos-arm64 (push) Successful in 2m45s
Test / rust-clippy (push) Successful in 3m12s
Test / rust-tests (push) Successful in 5m22s
Auto Tag / build-linux-amd64 (push) Successful in 10m55s
Auto Tag / build-windows-amd64 (push) Successful in 13m53s
Auto Tag / build-linux-arm64 (push) Successful in 14m11s
Reviewed-on: #55
2026-05-31 20:52:31 +00:00
Shaun Arman
1a9c3bd65a fix(sudo): enforce username scope and singleton row in sudo_config
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m20s
Test / frontend-tests (pull_request) Successful in 1m41s
Test / frontend-typecheck (pull_request) Successful in 1m43s
Test / rust-clippy (pull_request) Successful in 3m7s
PR Review Automation / review (pull_request) Successful in 4m11s
Test / rust-tests (pull_request) Successful in 4m27s
Fixes two bugs identified in the AI code review:

1. INSERT OR REPLACE with a freshly generated UUID never matches the
   existing primary key, so it appended rows instead of replacing.
   Switch to DELETE-then-INSERT to guarantee exactly one row.

2. Username defaulted to empty string. Resolve it to the current OS
   user (USER/LOGNAME env vars, fallback 'local') so credentials are
   always bound to a specific user identity.

   test_sudo_password now passes -u <username> to sudo so the test
   runs scoped to the stored user, not an arbitrary one.

UI: show the configured username prominently in status; relabel the
field and add a scope hint below it.

Tests: test_set_sudo_singleton_delete_then_insert, three username
resolution tests.
2026-05-31 15:46:29 -05:00
Shaun Arman
26507ad3ff fix(ci): install python3 in pr-review container (ubuntu:22.04 omits it)
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m22s
Test / frontend-typecheck (pull_request) Successful in 1m33s
Test / frontend-tests (pull_request) Successful in 1m31s
Test / rust-clippy (pull_request) Successful in 3m17s
PR Review Automation / review (pull_request) Successful in 4m18s
Test / rust-tests (pull_request) Successful in 4m25s
2026-05-31 15:37:10 -05:00
Shaun Arman
0057c570ba fix(ci): write curl body to file to avoid ARG_MAX limit
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m23s
Test / frontend-tests (pull_request) Successful in 1m30s
Test / frontend-typecheck (pull_request) Successful in 1m32s
Test / rust-clippy (pull_request) Successful in 3m19s
PR Review Automation / review (pull_request) Failing after 4m19s
Test / rust-tests (pull_request) Successful in 4m40s
The 147KB JSON body was being passed as a shell argument to curl,
hitting the kernel ARG_MAX limit. Write it to /tmp/body.json via
jq redirection and use curl --data @/tmp/body.json instead.
2026-05-31 15:32:16 -05:00
Shaun Arman
84bb3a20c1 fix(ci): use printf '%s' form to avoid format strings starting with hyphen
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m33s
Test / frontend-typecheck (pull_request) Successful in 1m37s
Test / frontend-tests (pull_request) Successful in 1m36s
Test / rust-clippy (pull_request) Successful in 3m31s
PR Review Automation / review (pull_request) Failing after 3m56s
Test / rust-tests (pull_request) Successful in 4m48s
bash printf treats format strings starting with '-' as option flags in
some environments. The POSIX-safe idiom is 'printf "%s\n" content'
where the format is always "%s\n" and the content is an argument.

Applied to all prompt printf calls. Also replaced '--' in prompt text
with single '-' to eliminate any remaining double-dash ambiguity.
2026-05-31 15:27:18 -05:00
Shaun Arman
6c825b1c73 fix(ci): remove remaining printf -- calls in Analyze with LLM step
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m34s
Test / frontend-tests (pull_request) Successful in 1m31s
Test / frontend-typecheck (pull_request) Successful in 1m33s
Test / rust-clippy (pull_request) Successful in 3m13s
PR Review Automation / review (pull_request) Failing after 3m50s
Test / rust-tests (pull_request) Successful in 4m27s
2026-05-31 15:18:02 -05:00
Shaun Arman
03cda08a33 fix(ci): fix grep invalid range and printf invalid option in pr-review
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m25s
Test / frontend-typecheck (pull_request) Successful in 1m30s
Test / frontend-tests (pull_request) Successful in 1m28s
Test / rust-clippy (pull_request) Successful in 3m17s
PR Review Automation / review (pull_request) Failing after 4m12s
Test / rust-tests (pull_request) Successful in 4m30s
1. SECRET_PATTERN had [A-Za-z0-9+/_\-!@#] -- backslash-escaped hyphen
   is invalid POSIX ERE; grep parsed it as a range with invalid bounds.
   Fix: move hyphen to end of class: [A-Za-z0-9+/_!@#-].

2. printf -- '---\n' fails with 'invalid option' in bash because the
   builtin does not accept -- as end-of-options. Removed -- from all
   four printf calls.
2026-05-31 15:12:46 -05:00
Shaun Arman
3d6270fb33 fix(ci): replace heredoc with printf to fix YAML block scalar breakage
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m34s
Test / frontend-tests (pull_request) Successful in 1m33s
Test / frontend-typecheck (pull_request) Successful in 1m35s
Test / rust-clippy (pull_request) Successful in 3m10s
PR Review Automation / review (pull_request) Failing after 4m19s
Test / rust-tests (pull_request) Successful in 4m23s
Shell heredocs with unindented bodies (line 1 content) terminate YAML
run: | block scalars. The YAML parser sees the unindented heredoc body
as leaving the block, making the workflow file unparseable -- Gitea
silently stops creating runs for a workflow with invalid YAML.

Replace the single-quoted heredoc prompt with a group of printf + cat
calls. Every line stays properly indented within the YAML block scalar.
Use jq --rawfile instead of --arg to load the prompt from a temp file,
which also eliminates shell escaping hazards for large strings.
2026-05-31 15:06:09 -05:00
Shaun Arman
f8c0d247e8 fix(ci): remove concurrency group that silently dropped pr-review runs
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 2m24s
Test / frontend-typecheck (pull_request) Successful in 2m21s
Test / frontend-tests (pull_request) Successful in 2m19s
Test / rust-clippy (pull_request) Successful in 3m34s
Test / rust-tests (pull_request) Successful in 4m50s
Gitea 1.22 cancel-in-progress does not behave like GitHub Actions: when
a new synchronize event arrives while a review is running, instead of
cancelling the running job and starting a new one, it drops the new run
silently. Remove the concurrency block entirely so every commit to a PR
gets its own review run.
2026-05-31 14:59:58 -05:00
Shaun Arman
4f70fd7fb8 fix(ci): fix backtick command substitution crash in pr-review prompt
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m18s
Test / frontend-tests (pull_request) Successful in 1m29s
Test / frontend-typecheck (pull_request) Successful in 1m33s
Test / rust-clippy (pull_request) Successful in 3m16s
Test / rust-tests (pull_request) Successful in 4m33s
The PROMPT string contained backtick-quoted text for the Evidence field
example. Inside a double-quoted bash string, backticks trigger command
substitution, causing 'exact: command not found' at runtime.

Fix: build the prompt using a single-quoted heredoc (no shell expansion
inside) then splice dynamic values via sed and python3 replace() instead
of shell variable interpolation.
2026-05-31 14:53:21 -05:00
Shaun Arman
93a0c3f1ee fix(ci): add codebase index to prompt; verify findings against full repo
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m19s
Test / frontend-tests (pull_request) Successful in 1m24s
Test / frontend-typecheck (pull_request) Successful in 1m27s
Test / rust-clippy (pull_request) Successful in 3m20s
Test / rust-tests (pull_request) Successful in 4m43s
PR Review Automation / review (pull_request) Failing after 3m11s
Two changes to reduce hallucinations in pr-review:

1. Codebase index (new step "Build codebase index"):
   Generates a compact manifest of everything that EXISTS in the project:
   - All registered Tauri commands (from lib.rs generate_handler![])
   - All TypeScript exports (from tauriCommands.ts)
   - All public Rust fn signatures in commands/
   - All DB migration names
   This index is prepended to the prompt so the model cannot invent
   functions like authenticate_sudo or continue_chat_history that are
   absent from both the index and the file contents.

2. Full-repo verification (updated "Verify findings" step):
   Previously only grepped changed files, which falsely tagged findings
   about unchanged-but-real code as UNVERIFIED. Now runs git ls-files
   to load all tracked source files, so verification only fails for
   code that genuinely does not exist anywhere in the codebase.

If qwen3-coder continues to hallucinate after these changes, swap the
model name on line 184 to bedrock-personal or claude-haiku.
2026-05-31 14:48:32 -05:00
Shaun Arman
cf5bc83b75 fix(ci): add post-generation evidence verification to pr-review
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m42s
Test / frontend-typecheck (pull_request) Successful in 1m42s
Test / frontend-tests (pull_request) Successful in 1m42s
Test / rust-clippy (pull_request) Successful in 3m16s
PR Review Automation / review (pull_request) Failing after 4m33s
Test / rust-tests (pull_request) Successful in 4m54s
qwen3-coder-next fabricates plausible-looking code in its Evidence
blocks instead of quoting from the actual files provided. This adds a
Python verification step that greps each fenced code block against the
real changed files and tags any finding whose evidence cannot be found
as UNVERIFIED.

This is a safeguard, not a fix — the model is fundamentally unreliable
for grounded code review. The longer-term fix is to replace qwen3-coder
with a model that stays grounded to context (Claude Haiku, devstral,
or deepseek-coder-v2 via the LiteLLM proxy / vLLM at 172.0.1.42).
2026-05-31 14:41:47 -05:00
Shaun Arman
6373f0b09c fix(ci): fix secret scrubbing regex that was deleting legitimate code lines
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m51s
Test / frontend-tests (pull_request) Successful in 1m51s
Test / frontend-typecheck (pull_request) Successful in 1m55s
Test / rust-clippy (pull_request) Successful in 3m11s
Test / rust-tests (pull_request) Successful in 4m27s
PR Review Automation / review (pull_request) Successful in 4m47s
The previous regex matched any line containing "password", "token", etc.
near certain punctuation characters. This silently removed function
signatures, variable declarations, and test assertions from the context
sent to the LLM — causing it to hallucinate 3 BLOCKERs per review:
- "function signature missing" (the `password: &str` param was scrubbed)
- "filter body empty" (the filter condition containing "password" was scrubbed)
- "password passed unencrypted" (the decrypt_token call line was scrubbed)

Fix: match actual credential VALUES only:
- Well-known token formats (AKIA..., ghp_..., xox...)
- keyword = "long_quoted_literal" (25+ chars, clearly a value not a name)
- Standalone base64 blob lines (60+ chars, PEM-style)

Never scrub a line just because it contains a credential-related word.
2026-05-31 14:33:44 -05:00
Shaun Arman
1de59db9f0 fix(ci): rewrite pr-review to send full file contents instead of diffs
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m23s
Test / frontend-tests (pull_request) Successful in 1m29s
Test / frontend-typecheck (pull_request) Successful in 1m30s
Test / rust-clippy (pull_request) Successful in 3m14s
PR Review Automation / review (pull_request) Successful in 4m24s
Test / rust-tests (pull_request) Successful in 4m26s
2026-05-31 14:24:56 -05:00
Shaun Arman
f6787accd6 fix(agentic): inline format arg in writeln! to satisfy clippy::uninlined_format_args
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m36s
Test / frontend-typecheck (pull_request) Successful in 1m34s
Test / frontend-tests (pull_request) Successful in 1m37s
Test / rust-clippy (pull_request) Successful in 3m7s
PR Review Automation / review (pull_request) Successful in 4m24s
Test / rust-tests (pull_request) Successful in 4m22s
Rust 1.88 enforces clippy::uninlined_format_args as a style lint under
-D warnings. Change `writeln!(stdin, "{}", password)` to the inline
form `writeln!(stdin, "{password}")`.
2026-05-31 14:19:29 -05:00
Shaun Arman
06956940e2 fix(ci): reduce AI review hallucinations in pr-review workflow
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m46s
Test / frontend-typecheck (pull_request) Successful in 1m49s
Test / frontend-tests (pull_request) Successful in 1m46s
Test / rust-clippy (pull_request) Failing after 3m12s
PR Review Automation / review (pull_request) Successful in 4m37s
Test / rust-tests (pull_request) Successful in 4m34s
Three changes:
- Exclude Cargo.lock/lockfiles from the diff — removes ~163 lines of
  hash noise that waste the review budget with no value
- Raise line cap from 500 to 3000 and add a truncation notice when
  the diff is cut, so the model knows the diff is incomplete
- Harden prompt: require quoted evidence for every finding; add explicit
  self-verification step for missing-identifier claims (search full diff
  before raising); tighten no-hallucinate instruction
2026-05-31 14:08:10 -05:00
Shaun Arman
cf1d5adb83 docs(analysis): document zip-slip safety guarantee in extract_docx_text
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m35s
Test / frontend-typecheck (pull_request) Successful in 2m16s
Test / frontend-tests (pull_request) Successful in 2m13s
Test / rust-clippy (pull_request) Failing after 3m43s
PR Review Automation / review (pull_request) Successful in 4m11s
Test / rust-tests (pull_request) Successful in 4m59s
Only a single hardcoded entry (word/document.xml) is ever accessed from
the ZIP archive; no arbitrary path extraction occurs, so path traversal
attacks cannot apply. Add a comment to make this invariant explicit for
future maintainers.
2026-05-31 13:57:38 -05:00
Shaun Arman
ed2e25f835 chore: update Cargo.lock for lopdf, zip, quick-xml deps 2026-05-31 13:51:08 -05:00
Shaun Arman
f47ec90d05 feat(upload): add safe file extension validation and binary text extraction
- Add extension allowlist (SAFE_TEXT_EXTENSIONS + SAFE_BINARY_EXTENSIONS)
  rejecting unsupported file types at both upload_log_file and
  upload_log_file_by_content entry points
- Add extract_text_content() with PDF text extraction via lopdf and
  DOCX extraction via zip+quick-xml
- Binary files (PDF/DOCX) get extracted text written to .extracted.txt
  for downstream PII detection
- Expand frontend file input accept list and add collapsible
  supported-formats disclosure element
- Add 11 unit tests covering allowlist logic and extraction paths
2026-05-31 13:50:59 -05:00
Shaun Arman
cd67a09a6a fix(ai,search): load history across all conversations; deep search related tables
AI history continuity: Changed the history-load query in chat_message to
JOIN ai_conversations and select by issue_id instead of single conversation_id.
This preserves full context when provider/model changes mid-triage.

Deep search: Added DISTINCT to list_issues SELECT and extended the search
filter with EXISTS subqueries covering ai_messages, resolution_steps,
log_files, and timeline_events. Ensures comprehensive search without
duplicate results.

Includes 11 new unit tests covering both features.
2026-05-31 13:50:29 -05:00
5e596f0cd3 fix(ci): pass release_tag as job output; fix equal-version case; drop git-describe [skip ci] 2026-05-23 22:48:14 +00:00
0c366180fa Merge pull request 'fix(ci): replace tea CLI with curl; honour Cargo.toml version for tags' (#54) from fix/ci-auto-tag-tea into master
Some checks failed
Test / rust-fmt-check (push) Successful in 1m40s
Test / frontend-typecheck (push) Successful in 2m15s
Test / rust-tests (push) Has been cancelled
Test / frontend-tests (push) Has been cancelled
Test / rust-clippy (push) Has been cancelled
Auto Tag / autotag (push) Successful in 6s
Auto Tag / wiki-sync (push) Successful in 7s
Auto Tag / changelog (push) Failing after 35s
Auto Tag / build-macos-arm64 (push) Successful in 3m23s
Auto Tag / build-linux-amd64 (push) Successful in 8m36s
Auto Tag / build-windows-amd64 (push) Successful in 10m10s
Auto Tag / build-linux-arm64 (push) Successful in 10m24s
2026-05-23 22:39:23 +00:00
Shaun Arman
28f579a1ae fix: bump tauri.conf.json version to 0.3.0
Some checks failed
Test / frontend-typecheck (pull_request) Successful in 1m50s
Test / frontend-tests (pull_request) Successful in 1m45s
Test / rust-fmt-check (pull_request) Successful in 1m55s
Test / rust-clippy (pull_request) Successful in 3m24s
Test / rust-tests (pull_request) Successful in 5m38s
PR Review Automation / review (pull_request) Has been cancelled
Cargo.toml was updated to 0.3.0 for the MCP feature but tauri.conf.json
was missed. Bundle artifact filenames are derived from tauri.conf.json,
so all builds were producing files named 0.2.68.
2026-05-23 17:36:38 -05:00
047772d719 fix(ci): replace tea with curl, honour Cargo.toml version [skip ci] 2026-05-23 22:31:45 +00:00
Shaun Arman
75f8a006ea fix(ci): replace tea CLI with curl in changelog steps; read Cargo.toml for version
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 1m33s
Test / frontend-typecheck (pull_request) Successful in 1m40s
Test / frontend-tests (pull_request) Successful in 1m52s
Test / rust-clippy (pull_request) Successful in 3m25s
PR Review Automation / review (pull_request) Successful in 4m21s
Test / rust-tests (pull_request) Successful in 4m29s
tea is not available in alpine:latest containers. Replace both tea calls
with curl API requests against the Gitea releases endpoint.

Also: auto-tag now reads src-tauri/Cargo.toml version first. If it is
ahead of the latest git tag (major/minor bump), that version is used
directly instead of incrementing the patch.
2026-05-23 17:30:41 -05:00
ea7f484ce6 Merge pull request 'feat(mcp): add MCP Server Support' (#53) from feature/mcp-server-support into master
Some checks failed
Auto Tag / autotag (push) Successful in 7s
Auto Tag / wiki-sync (push) Successful in 7s
Auto Tag / changelog (push) Failing after 1m19s
Test / rust-fmt-check (push) Successful in 1m42s
Test / frontend-tests (push) Successful in 2m3s
Test / frontend-typecheck (push) Successful in 2m7s
Test / rust-clippy (push) Successful in 3m30s
Test / rust-tests (push) Successful in 5m12s
Auto Tag / build-linux-amd64 (push) Successful in 10m1s
Auto Tag / build-windows-amd64 (push) Successful in 12m0s
Auto Tag / build-linux-arm64 (push) Successful in 11m43s
Auto Tag / build-macos-arm64 (push) Failing after 12m46s
Reviewed-on: #53
2026-05-23 22:15:10 +00:00
Shaun Arman
28cfcf1ef4 fix(mcp): add timeouts, delete audit log, OAuth state nonce; improve PR review prompt
All checks were successful
Test / frontend-typecheck (pull_request) Successful in 1m54s
Test / rust-fmt-check (pull_request) Successful in 2m0s
Test / frontend-tests (pull_request) Successful in 1m53s
Test / rust-clippy (pull_request) Successful in 3m33s
PR Review Automation / review (pull_request) Successful in 4m54s
Test / rust-tests (pull_request) Successful in 4m57s
- call_tool: 30s hard timeout via tokio::time::timeout
- discover_server: 60s hard timeout wrapping full connect+discover sequence
- delete_mcp_server: write_audit_event before cascade delete, capturing
  server name, tool count, and resource count
- initiate_mcp_oauth: append cryptographically random state nonce for CSRF
- pr-review.yml: rewrite prompt to require line-quoted evidence for every
  finding and eliminate hallucinated false positives
2026-05-23 17:08:23 -05:00
Shaun Arman
8e1145ec7a fix(ci): use qwen3-coder-next model for PR review
Some checks failed
Test / rust-fmt-check (pull_request) Has been cancelled
Test / frontend-typecheck (pull_request) Has been cancelled
Test / rust-clippy (pull_request) Has been cancelled
Test / rust-tests (pull_request) Has been cancelled
Test / frontend-tests (pull_request) Has been cancelled
PR Review Automation / review (pull_request) Successful in 6m46s
2026-05-23 16:54:26 -05:00