feat: harden send file idempotency audit
This commit is contained in:
@@ -240,8 +240,8 @@ Continuous execution plan R6f-R14 is approved and execution has started:
|
||||
- Plan file: `docs/superpowers/plans/2026-07-10-r6f-r14-continuous-execution-plan.md`.
|
||||
- Scope: 15 ordered rounds covering send-message connector/gate hardening, send-file preview/idempotency/package, receive-file download preview, receive-message reconciliation, end-to-end business smoke, and release-candidate report.
|
||||
- Execution rule after approval: one round at a time, status-card update, verification, commit, push, then continue automatically until an evidence-only blocker requires user action.
|
||||
- Last completed round: R7 send-file preview tool.
|
||||
- Next active round: R8 send-file idempotency and audit hardening.
|
||||
- Last completed round: R8 send-file idempotency and audit hardening.
|
||||
- Next active round: R9 send-file upload evidence package.
|
||||
|
||||
R6g send audit and idempotency replay diagnostics is complete:
|
||||
|
||||
@@ -305,3 +305,13 @@ R7 send-file preview tool is complete:
|
||||
- `execution_mode="production"` returns structured blocked metadata; no upload, click, type, hook, network capture, or client mutation is introduced.
|
||||
- Verification passed: focused send-file tests, 10-tool MCP registration test, `go test ./...`, `go build ./cmd/isphere-mcp`, `scripts\verify-go-mcp.ps1`, and `go run ./cmd/isphere-capability-smoke`.
|
||||
- Next node: R8 send-file idempotency and audit hardening.
|
||||
|
||||
R8 send-file idempotency and audit hardening is complete:
|
||||
|
||||
- Added `ISPHERE_SEND_FILE_AUDIT_PATH` and `ISPHERE_SEND_FILE_IDEMPOTENCY_PATH` support.
|
||||
- Duplicate same target/file/idempotency key returns `duplicate_detected=true` and remains no-send.
|
||||
- Reusing the same idempotency key for a different target or file hash returns structured blocked metadata with `conflict_detected=true`.
|
||||
- Send-file audit/idempotency JSONL stores hashes, target refs, size, result, and side-effect flags; it does not store raw file content, raw local file path, or raw idempotency key.
|
||||
- Production file upload remains blocked with `production_send_enabled=false` and `real_send_attempted=false`.
|
||||
- Verification passed: focused send-file tests, `go test ./...`, `go build ./cmd/isphere-mcp`, `scripts\verify-go-mcp.ps1`, and `go run ./cmd/isphere-capability-smoke`.
|
||||
- Next node: R9 send-file upload evidence package.
|
||||
|
||||
@@ -284,7 +284,14 @@ Send-file preview requires an explicit allowed directory. Put only the files you
|
||||
$env:ISPHERE_SEND_FILE_ALLOWED_DIR = "E:\coding\codex\isphere-ai-bridge\runs\send-file-preview"
|
||||
```
|
||||
|
||||
`isphere_send_file` rejects `file_path` values outside that directory. It computes file SHA256 and size, but does not upload, click, type, or return file content.
|
||||
Optional send-file audit/idempotency paths:
|
||||
|
||||
```powershell
|
||||
$env:ISPHERE_SEND_FILE_AUDIT_PATH = "E:\coding\codex\isphere-ai-bridge\runs\send-audit\send-file-preview.jsonl"
|
||||
$env:ISPHERE_SEND_FILE_IDEMPOTENCY_PATH = "E:\coding\codex\isphere-ai-bridge\runs\send-audit\send-file-idempotency.jsonl"
|
||||
```
|
||||
|
||||
`isphere_send_file` rejects `file_path` values outside that directory. It computes file SHA256 and size, but does not upload, click, type, or return file content. If `ISPHERE_SEND_FILE_IDEMPOTENCY_PATH` is set, duplicate same-key/same-target/same-file preview calls set `duplicate_detected=true`; reusing the same key for a different target or file hash returns blocked metadata with `conflict_detected=true`. The audit/idempotency JSONL stores file hash, size, target ref, and hashed idempotency key; it does not store raw file content, raw local file path, or raw idempotency key.
|
||||
|
||||
R6g adds a local diagnostic for replaying the redacted audit/idempotency files without opening iSphere:
|
||||
|
||||
|
||||
@@ -594,19 +594,19 @@ git push gitea main
|
||||
- Duplicate same target/file/idempotency returns `duplicate_detected=true` with no second send.
|
||||
- Reusing the same idempotency key for a different target or file hash returns `conflict_detected=true`.
|
||||
|
||||
- [ ] **Step 1: Write duplicate test**
|
||||
- [x] **Step 1: Write duplicate test**
|
||||
|
||||
Add `TestISphereSendFileDuplicateIdempotencyDetected`: same target, same file hash, same idempotency key called twice; second response has `duplicate_detected=true` and `real_send_attempted=false`.
|
||||
|
||||
- [ ] **Step 2: Write conflict test**
|
||||
- [x] **Step 2: Write conflict test**
|
||||
|
||||
Add `TestISphereSendFileIdempotencyConflictBlocked`: same idempotency key with a different file hash returns `send_status="blocked"` and `conflict_detected=true`.
|
||||
|
||||
- [ ] **Step 3: Implement audit and idempotency state**
|
||||
- [x] **Step 3: Implement audit and idempotency state**
|
||||
|
||||
Reuse the message idempotency pattern or extract a shared small helper only if it reduces duplication without changing message behavior.
|
||||
|
||||
- [ ] **Step 4: Verify and commit**
|
||||
- [x] **Step 4: Verify and commit**
|
||||
|
||||
```powershell
|
||||
git diff --check
|
||||
@@ -621,6 +621,15 @@ git push gitea main
|
||||
|
||||
**Acceptance gate:** File upload remains blocked, but duplicate/conflict behavior is deterministic.
|
||||
|
||||
**R8 Result:**
|
||||
|
||||
- Added send-file audit and idempotency state with `ISPHERE_SEND_FILE_AUDIT_PATH` and `ISPHERE_SEND_FILE_IDEMPOTENCY_PATH`.
|
||||
- Duplicate same target/file/idempotency key now returns `duplicate_detected=true` and remains planned/no-send.
|
||||
- Reusing the same idempotency key for a different target or file hash returns `send_status="blocked"` and `conflict_detected=true`.
|
||||
- Send-file audit/idempotency JSONL stores file hash, size, target ref, result, side-effect flags, and hashed idempotency key; it does not store raw file content, raw local file path, or raw idempotency key.
|
||||
- `scripts/verify-go-mcp.ps1` now asserts `send_file_duplicate_detected=true` and `send_file_conflict_blocked=true` while keeping `send_file_production_enabled=false`.
|
||||
- Verification passed: `git diff --check`, `go test ./internal/tools -run TestISphereSendFile -v`, `go test ./...`, `go build ./cmd/isphere-mcp`, `scripts\verify-go-mcp.ps1`, and `go run ./cmd/isphere-capability-smoke`.
|
||||
|
||||
---
|
||||
|
||||
### R9: Send-file upload evidence package
|
||||
|
||||
Reference in New Issue
Block a user