Commit Graph

6 Commits

Author SHA1 Message Date
shankar0123 0e29c416b1 refactor(handler,repo): replace strings.Contains error dispatch with typed sentinels (S-2)
Closes one 2026-04-24 audit finding (P2):

  - cat-s6-efc7f6f6bd50: 30 strings.Contains(err.Error(), ...) sites
    in internal/api/handler/ — brittle to repository-layer message
    changes, untyped against the actual failure mode.

Approach (Option B from prompt design notes):
  - New typed sentinels in internal/repository/errors.go:
      ErrNotFound, ErrForeignKeyConstraint
      IsForeignKeyError(err) helper (the only place substring
      matching at the lib/pq boundary is allowed; isolates the
      DB-driver string knowledge to one function).
  - New typed sentinel in internal/domain/errors.go:
      ErrValidation (reserved for future per-entity validation
      wrappers; not yet used by all handlers).
  - 49 sites in internal/repository/postgres/*.go updated to wrap
    sql.ErrNoRows-derived errors via fmt.Errorf("...: %w",
    repository.ErrNotFound).
  - 18 not-found handler sites + 2 FK-constraint handler sites
    refactored to errors.Is(err, repository.ErrNotFound) /
    repository.IsForeignKeyError(err).
  - 23 inline `fmt.Errorf("X not found")` test fixtures across
    handler tests rewrapped to wrap repository.ErrNotFound.
  - test_utils.go::ErrMockNotFound rewrapped to wrap
    repository.ErrNotFound; renewal_policy.go closure docblock
    updated to reflect the new convention.
  - integration test mockJobRepository.Get wraps repository.ErrNotFound.

CI regression guardrail:
- .github/workflows/ci.yml::"Forbidden strings.Contains(err.Error())
  regression guard (S-2)" greps for the three patterns ("not found",
  "violates foreign key", "RESTRICT") under internal/api/handler/
  and fails the build on regression.

Verification:
- go build ./... — clean
- go vet ./... — clean
- go test ./... -short -count=1 — all packages pass (handler +
  repository + service + integration)
- golangci-lint v2.11.4 run ./... — 0 issues
- S-2 guardrail dry-run on post-fix tree → empty (good)
- All sibling guardrails (S-1, G-3, D-1+D-2, B-1, L-1, H-1, C-1, F-1, P-1) pass

Audit findings closed:
- cat-s6-efc7f6f6bd50 (P2)

Deferred follow-ups:
- 6 domain-specific substring patterns still inline in handlers
  ("cannot approve", "cannot reject", "cannot be parsed",
  "no certificates found", "challenge password", "invalid"/
  "required" validation chains in profiles + agent_groups). Each
  needs its own typed sentinel, scoped per service. Documented
  by the S-2 CI guardrail's allowlist for closure-comments only.
- Per-entity not-found sentinels (Option A — ErrCertificateNotFound,
  ErrAgentNotFound, etc.) deferred. Generic ErrNotFound covers the
  current dispatch needs; per-entity precision would let handlers
  return entity-aware error bodies without a domain.Type field,
  but not blocking.
2026-04-25 17:54:14 +00:00
shankar0123 eb14236166 M-2 PR-B: Collapse IssuerService + TargetService to ctx-first signatures
- Delete bare TestConnection wrapper in IssuerService; rename
  TestConnectionWithContext → TestConnection
- Delete TestTargetConnection delegate shim in TargetService (canonical
  TestConnection already ctx-first)
- Add ctx first param to 10 handler-interface methods
  (ListIssuers/GetIssuer/CreateIssuer/UpdateIssuer/DeleteIssuer and
  ListTargets/GetTarget/CreateTarget/UpdateTarget/DeleteTarget)
- Replace 16 context.Background() call sites with received ctx
- Thread r.Context() through 12 HTTP handler sites in issuers.go and
  targets.go (outer TargetHandler.TestTargetConnection HTTP method name
  preserved for router compatibility)
- Update MockIssuerService, MockTargetService, and mockTargetService
  (integration) for ctx-first forwarding; update test callsite literals

Audit complete. Commit: 1f6cf0eafa. Sections: 12. Findings: 2/7/10/4/6.
2026-04-18 00:46:58 +00:00
shankar0123 68f6fd474b fix: return 409 on duplicate issuer name, improve error handling and onboarding defaults
Closes #7. The issuer create/update handlers swallowed all service errors
as generic 500s. Now differentiates: 409 for UNIQUE constraint violations,
400 for unsupported issuer type, 404 for not-found on update, 500 for
unknown errors. Adds structured error logging via slog.

OnboardingWizard now pre-populates config field defaults when a type is
selected (matching IssuersPage behavior), preventing empty required fields
from causing silent failures.

install-agent.sh hardened for curl|bash usage: --agent-id flag, =value
syntax, /dev/tty stdin reopening, proper stderr routing in download_binary,
non-interactive install examples in help text, and updated wizard commands.

Adds adversarial security tests for EST, path traversal, and query
injection handlers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 19:18:32 -04:00
shankar0123 0f4a1b268b fix: handle 204 No Content in fetchJSON, add FK-aware delete errors, v2 screenshots
Frontend: fetchJSON now returns empty object on 204 instead of failing
to parse empty body — fixes silent delete failures across all entities.
Added onError callbacks to owner/team delete mutations to surface errors.

Backend: owner and issuer delete handlers return 409 Conflict with
descriptive messages when FK constraints block deletion, instead of
generic 500.

Added 15 v2 dashboard screenshots, updated README screenshot section,
logo asset, page count references (18→full), and QA guide with FK
constraint test coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 05:03:50 -04:00
shankar0123 9e6756d02f Implement M5: hardening, input validation, and Vite+React+TS dashboard
Backend hardening:
- Fix 6 nginx.go non-constant format string build errors
- Add validation.go with hostname, PEM, and enum validators
- Apply input validation to all POST/PUT handlers (certificates,
  agents, CSR, policies, teams, owners, targets, issuers)
- Fix unchecked JSON decode in TriggerDeployment handler

Frontend (Vite + React + TypeScript):
- Migrate from single-file SPA to proper build pipeline
- 7 pages: Dashboard, Certificates (list+detail), Agents, Jobs,
  Notifications, Policies, Audit Trail
- TanStack Query for server state with auto-refetch intervals
- Certificate detail with version history and renewal trigger
- Job cancellation, status/type filtering, expiry countdowns
- Reusable components: DataTable, StatusBadge, ErrorState, PageHeader
- Dark theme with Tailwind CSS, sidebar nav via React Router

Server integration:
- Go server serves web/dist/ (Vite output) with SPA fallback
- Falls back to web/index.html for legacy mode
- .gitignore updated for web/node_modules/ and web/dist/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 01:19:19 -04:00
shankar0123 d395776a95 Initial scaffold: certificate control plane v0.1.0 2026-03-14 08:22:17 -04:00