Commit Graph
4 Commits
Author SHA1 Message Date
Quick104andClaude Fable 5 2d5d4980de fix(diagnostics): address round-2 review findings on PR #445
- settings.go: cap the parsed cleanup interval at 7 days before converting to
  time.Duration so a huge configured value can't overflow int64 nanoseconds and
  wrap into a tiny/negative interval; add boundary tests.
- settings.go: propagate genuine settings read failures from LoadSettings
  (missing/empty -> default, error -> fail) so a transient DB error surfaces
  retryably instead of silently reporting uploads disabled or wrong quotas.
- bundle.go: validate non-manifest bundle entries while streaming with bounded
  memory -- device.json and crash/*.json must be a single JSON object,
  logs.jsonl/breadcrumbs.jsonl must be newline-delimited JSON objects with a
  per-line byte cap (new contract.MaxLogLineBytes); binary members stay opaque.
- diagnostics upload handler: extend the read deadline per-route via
  http.ResponseController.SetReadDeadline (10m) so slow mobile uploads of large
  bundles aren't cut off by the shared 30s server ReadTimeout.
- web admin download: request the ?proxy=1 streaming path directly so downloads
  work when S3Private is only server-reachable and errors can surface in-page.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012e3QjbPo96ed9Mn2qRiUkh
2026-07-21 11:29:02 -04:00
Quick104andClaude Fable 5 a6348b3dc5 fix(diagnostics): address PR #445 review findings
- bundle: reject tar entry names that differ from their trimmed form instead
  of normalizing padded names into the allowlist
- repo: reserve expected bytes on receiving rows and count receiving+ready in
  the per-user byte quota so concurrent/multi-node uploads can't overshoot
- contract: require the crash object for event report types and keep it absent
  for manual; add contract tests
- settings/service: seed diagnostics.server_instance_id atomically via
  insert-if-absent and adopt the winning value across nodes
- bundle/service: capture the embedded manifest.json during ValidateBundle and
  reject reports whose embedded manifest disagrees with the part-1 manifest
  (minus archive); add tests
- admin: delete the DB row before the blob on DeleteReport; log bucket/key when
  the blob delete fails instead of leaving a visible report with a missing bundle
- bundle: reject PAX/GNU tar formats and extension records that smuggle bytes
  past validation; add a PAX-archive rejection test
- migration: add CHECK constraints for state, report_type, and platform
- docs: add text/jsonc language identifiers to the two unfenced code blocks
- cleanup: log-and-continue per report and aggregate errors so one poisoned
  report no longer blocks the whole run; update tests
- tasks: give diagnostics its own cleanup interval key instead of reusing the
  opslog key, and bound the startup settings lookup

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012e3QjbPo96ed9Mn2qRiUkh
2026-07-21 10:03:11 -04:00
Quick104andClaude Fable 5 f965a489bd fix(diagnostics): align bundle contract with real tar writers
Two validator behaviors made the contract unimplementable for clients
using standard tar libraries:

- Any byte after the tar end-of-archive marker was rejected, but GNU
  tar, Python tarfile, and Apache Commons Compress all pad the archive
  with zero blocks to a record boundary. Accept up to 64 KiB of zero
  padding; any non-zero trailing data is still rejected.

- uncompressed_bytes was computed as the sum of entry payloads, which
  no tar-producing client observes. Define it as the total decompressed
  tar stream (headers, end-of-archive marker, and padding included) —
  the byte count between a client's tar writer and gzip writer, and
  what gzip -l reports. Documented in the design doc and contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012e3QjbPo96ed9Mn2qRiUkh
2026-07-21 08:17:18 -04:00
Quick104andClaude Fable 5 4fa84a661a feat(diagnostics): client diagnostics server foundation
Implements slice 1 of docs/design/2026-07-19-client-diagnostics.md: the
versioned contract (schemas, fixtures, Go validator), storage-validated
diagnostics.uploads_enabled gate, account-scoped status endpoint, hardened
streaming multipart ingest with quota reservation and a receiving/ready/
failed report state machine, S3 streaming puts, acting-admin report API
(list/detail/download/delete with audit events), and the retention +
orphan-reconciliation cleanup task.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XppCCycoaskCsW7ja1fZct
2026-07-20 11:13:52 -04:00