Commit Graph

16 Commits

Author SHA1 Message Date
Chris Anderson
5bce1bd39b Phase 2.4: Testing & Deployment
Some checks are pending
CI / go (push) Waiting to run
CI / docker (push) Waiting to run
CI / lint-go (push) Waiting to run
CI / lint-docs (push) Waiting to run
CI / check-paperclip (push) Waiting to run
- Wire face service into main.go with FACE_SERVICE_ENABLED toggle
- Add integration tests for AWS Rekognition (build tag: integration)
- Add performance benchmarks for face operations (build tag: performance)
- Fix PhotoRepository interface to use store types directly
- Remove duplicate PhotoInfo/FaceEmbeddingInfo types from face package
- Add go.mod replace directive for local module resolution

Integration tests: go test -tags=integration ./internal/face/...
Performance tests: go test -tags=performance -bench=. ./internal/face/...
Standard tests: go test ./...
2026-06-26 05:50:07 +02:00
Chris Anderson
a63d2dbf62 Add security headers, rate limiting, and input validation middleware
- SecurityHeaders: X-Frame-Options, CSP, HSTS, X-XSS-Protection, etc.
- RateLimiter: in-memory sliding window, 100 req/min per IP
- ValidateSlug: alphanumeric + hyphens, 3-100 chars
- SanitizeSearchQuery: strips injection-prone characters
- REDIS_URL env var passthrough in docker-compose for future caching

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-25 22:18:21 +02:00
Chris Anderson
4a24f33f17 Fix TestGuestFaceSearch to handle missing face service 2026-06-25 21:35:29 +02:00
Chris Anderson
51aaf3c9d2 Add face package import to handler
- Import internal/face package in handler.go
- Add FaceService field to Handler struct
- Add NewWithFaceService constructor
- Update go.mod with AWS SDK dependencies

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-25 21:16:50 +02:00
Chris Anderson
6568af4dba Add face service package for AWS Rekognition integration 2026-06-25 21:15:57 +02:00
Chris Anderson
4bf37faf4f Add face service package for AWS Rekognition integration
- Client interface and MockClient for testing
- Service layer with IndexPhoto and SearchFaces methods
- CacheService interface and MemoryCache implementation
- Configuration with environment variable support
- Error types and user-facing messages
- Unit tests for service layer

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-25 21:11:45 +02:00
Riley Zhang
12775f836c Phase 4: Production readiness - graceful shutdown, health checks, load testing, pprof
- Graceful shutdown: SIGINT/SIGTERM handling with 5s timeout
- Readiness probe (/readyz): pings database before reporting ready
- Connection pool: documented MaxOpenConns(1) for SQLite single-writer constraint
- Load test tool: cmd/loadtest with configurable concurrency/total requests
- Shell script: scripts/load-test.sh for quick load testing
- pprof endpoints: /debug/pprof/* when HATCH_DEBUG env var is set

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-24 05:26:42 +02:00
Riley Zhang
ceaf7f9fb5 test: add unit tests for handler and store packages
- Added TestSearchRequests for store package (0% → 100% coverage)
- Added TestOpenInMemory for store package Open function
- Added TestNewSQLiteRepoNilDB for error handling
- Added TestV1ReplayRequest for handler package (0% → 100% coverage)
- Added TestPrettyJSON and TestFormatTime for inspect helpers
- Added TestJoinPath for path joining utility
- Added TestHandleMockReturnsErrorOnInvalidJSON
- Added TestInspectReturnsHTMLErrorOnRepoFailure
- Added TestCaptureMissingEndpointID, TestV1CaptureRequestMissingEndpoint, TestV1ListRequestsMissingEndpoint

Coverage improvements:
- Handler: 77.1% → 82.2%
- Store: 61.1% → 82.2%

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-24 05:07:50 +02:00
Riley Zhang
6f03ff2465 Add linting, formatting, and test infrastructure for Phase 1
- Add .golangci.yml with sensible linting rules
- Add Makefile with test, lint, fmt, vet, build targets
- Enhance CI pipeline with Go formatting check and golangci-lint job
- Create shared testutil.FakeRepository for handler tests
- Refactor handler tests to use shared FakeRepository
- Add data/ and coverage.out to .gitignore

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-24 04:59:52 +02:00
SoftwareEngineer
dc0394cada Implement JSON API layer for Hatch (ELF-160)
Add v1 JSON API endpoints alongside existing HTML endpoints:

- POST /v1/endpoints/{id}/requests: Capture JSON request
- GET /v1/endpoints/{id}/requests: List or search requests
- POST /v1/endpoints/{id}/requests/{reqId}/replay: Replay captured request
- PUT /v1/endpoints/{id}/mock: Set mock configuration
- GET /v1/endpoints/{id}/openapi.json: OpenAPI 3.1 specification

Add SearchRequests to Repository interface and implement simple LIKE search.
Write integration tests for all v1 endpoints. Ensure backward compatibility
with existing HTML endpoints.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-23 09:53:13 +02:00
SoftwareEngineer
7668661f74 Add mock handler tests and fix env leakage in main_test.go
- Added TestMockSetsAndConfiguresResponse: verifies PUT /e/{id}/mock stores mock config
- Added TestMockReturnsConfiguredResponseOnCapture: verifies capture returns mock response
  when one is configured, and the request is still recorded
- Added TestMockAutoCreatesEndpointOnSet: verifies mock endpoint auto-creates if missing
- Fixed TestHealthzSmoke to use t.Setenv instead of os.Setenv to prevent env leak

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-22 19:13:12 +02:00
SoftwareEngineer
8c5e75b06b feat(inspect): polish server-rendered request list page
- Add formatTime template func for human-readable timestamps (just now, 2m ago, etc.)
- Add client-side formatTimeStr for SSE live-update timestamps
- Fix SSE body rendering: buildRequestBody() populates headers/query/body for live-added requests
- Fix SSE body encoding: use string in sseRequest to avoid base64 encoding of []byte
- Add inspect handler tests: renders HTML, empty state, auto-creates endpoint
- Timestamps include title attr with full ISO timestamp for hover detail
2026-06-22 19:09:58 +02:00
SoftwareEngineer
cf5b2f185c fix(sse): flush response headers before blocking select loop
Without flusher.Flush() after WriteHeader, the HTTP response headers
were buffered and never sent to the client, causing SSE clients to hang
indefinitely waiting for the initial response.

- Add flusher.Flush() after WriteHeader in HandleSSE
- Add TestSSEStreamReceivesEventOnCapture integration test:
  starts test server, subscribes to SSE, captures a request, and
  verifies the event arrives within 2s

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-22 19:05:50 +02:00
SoftwareEngineer
4256d34c27 feat: add one-click replay for captured requests
- Add POST /e/{endpoint}/requests/{id}/replay endpoint
- Replay re-sends captured method, path, headers, query, body to target URL
- Response includes target status code, headers, body (truncated 64KB)
- SSRF guard: denies replay to private/loopback by default
- Opt-in env var HATCH_ALLOW_PRIVATE_REPLAY=true for local dev
- Server-rendered inspect page at GET /e/{endpoint} with replay button UI
- SSE live stream for new requests (EventSource)
- Mock configuration at PUT /e/{endpoint}/mock
- Store: GetRequest, GetMock, SetMock methods added
- Chi router migration from stdlib ServeMux
- 26 passing tests including replay unit tests and E2E capture-to-replay

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-22 16:58:42 +02:00
SoftwareEngineer
5bbf995f32 Fix capture: endpoint ID/URL mismatch, routing, and extractID
- Use URL as endpoint ID so handler path-segment lookups resolve correctly.
  Previously CreateEndpoint generated a random UUID for the ID, but the
  handler always queries by the path segment — every GetEndpoint call
  missed, causing duplicate UNIQUE violations on subsequent requests
  and orphaned request records (endpoint_id mismatch).

- Register both /{endpoint} and /{endpoint}/ patterns so bare and
  nested capture paths both route to the handler (Go 1.22+ ServeMux).

- Strip query string in extractID for robustness, even though the
  library never sends ? in r.URL.Path.

- Remove unused net/http import from handler_test.go (caught by vet).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-22 14:38:50 +02:00
CTO
90c3f6285d feat: mock endpoint — configure response per endpoint
- Add mock_status, mock_headers, mock_body columns to endpoints schema
- Add MockConfig struct and UpsertMock to Repository interface
- Implement UpsertMock in sqliteRepo (INSERT ON CONFLICT UPDATE)
- Update GetEndpoint to return mock configuration when present
- Add PUT /e/{endpoint_id}/mock handler with JSON body {status, headers, body}
- Add catch-all /{endpoint_id} handler returning mock or default 200
- Header sanitization: only allow Content-Type, Cache-Control, X-*
- Wire handler into cmd/hatch main with SQLite store
- Fix Dockerfile: COPY go.sum for reproducible builds
- Tests: store mock CRUD, handler mock config + header sanitization

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-22 14:32:53 +02:00