chore: add GSD codebase map with 7 analysis documents

Parallel analysis of tech stack, architecture, structure,
conventions, testing patterns, integrations, and concerns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-23 19:13:23 +01:00
parent 4358de87ba
commit 96c4012e2f
7 changed files with 1483 additions and 0 deletions

View File

@@ -0,0 +1,198 @@
# Coding Conventions
**Analysis Date:** 2026-03-23
## Naming Patterns
**Go Files:**
- Package-level source files use the package name: `diunwebhook.go`
- Test files follow Go convention: `diunwebhook_test.go`
- Test-only export files: `export_test.go`
- Entry point: `main.go` inside `cmd/diunwebhook/`
**Go Functions:**
- PascalCase for exported functions: `WebhookHandler`, `UpdateEvent`, `InitDB`, `GetUpdates`
- Handler functions are named `<Noun>Handler`: `WebhookHandler`, `UpdatesHandler`, `DismissHandler`, `TagsHandler`, `TagByIDHandler`, `TagAssignmentHandler`
- Test functions use `Test<FunctionName>_<Scenario>`: `TestWebhookHandler_BadRequest`, `TestDismissHandler_NotFound`
**Go Types:**
- PascalCase structs: `DiunEvent`, `UpdateEntry`, `Tag`
- JSON tags use snake_case: `json:"diun_version"`, `json:"hub_link"`, `json:"received_at"`
**Go Variables:**
- Package-level unexported variables use short names: `mu`, `db`, `webhookSecret`
- Local variables use short idiomatic Go names: `w`, `r`, `err`, `res`, `n`, `e`
**TypeScript Files:**
- Components: PascalCase `.tsx` files: `ServiceCard.tsx`, `AcknowledgeButton.tsx`, `Header.tsx`, `TagSection.tsx`
- Hooks: camelCase with `use` prefix: `useUpdates.ts`, `useTags.ts`
- Types: camelCase `.ts` files: `diun.ts`
- Utilities: camelCase `.ts` files: `utils.ts`, `time.ts`, `serviceIcons.ts`
- UI primitives (shadcn): lowercase `.tsx` files: `badge.tsx`, `button.tsx`, `card.tsx`, `tooltip.tsx`
**TypeScript Functions:**
- camelCase for regular functions and hooks: `fetchUpdates`, `useUpdates`, `getServiceIcon`
- PascalCase for React components: `ServiceCard`, `StatCard`, `AcknowledgeButton`
- Helper functions within components use camelCase: `getInitials`, `getTag`, `getShortName`
- Event handlers prefixed with `handle`: `handleDragEnd`, `handleNewGroupSubmit`
**TypeScript Types:**
- PascalCase interfaces: `DiunEvent`, `UpdateEntry`, `Tag`, `ServiceCardProps`
- Type aliases: PascalCase: `UpdatesMap`
- Interface properties use snake_case matching the Go JSON tags: `diun_version`, `hub_link`
## Code Style
**Go Formatting:**
- `gofmt` enforced in CI (formatting check fails the build)
- No additional Go linter (golangci-lint) configured
- `go vet` runs in CI
- Standard Go formatting: tabs for indentation
**TypeScript Formatting:**
- No ESLint or Prettier configured in the frontend
- No formatting enforcement in CI for frontend code
- Consistent 2-space indentation observed in all `.tsx` and `.ts` files
- Single quotes for strings in TypeScript
- No semicolons (observed in all frontend files)
- Trailing commas used in multi-line constructs
**TypeScript Strictness:**
- `strict: true` in `tsconfig.app.json`
- `noUnusedLocals: true`
- `noUnusedParameters: true`
- `noFallthroughCasesInSwitch: true`
- `noUncheckedSideEffectImports: true`
## Import Organization
**Go Import Order:**
Standard library imports come first, followed by a blank line, then the project import using the module alias:
```go
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"testing"
diun "awesomeProject/pkg/diunwebhook"
)
```
- The project module is aliased as `diun` in both `main.go` and test files
- The blank-import pattern `_ "modernc.org/sqlite"` is used for the SQLite driver in `pkg/diunwebhook/diunwebhook.go`
**TypeScript Import Order:**
1. React and framework imports (`react`, `@dnd-kit/core`)
2. Internal imports using `@/` path alias (`@/hooks/useUpdates`, `@/components/Header`)
3. Type-only imports: `import type { Tag, UpdatesMap } from '@/types/diun'`
**Path Aliases:**
- `@/` maps to `frontend/src/` (configured in `vite.config.ts` and `tsconfig.app.json`)
## Error Handling
**Go Patterns:**
- Handlers use `http.Error(w, message, statusCode)` for all error responses
- Error messages are lowercase: `"bad request"`, `"internal error"`, `"not found"`, `"method not allowed"`
- Internal errors are logged with `log.Printf` before returning HTTP 500
- Decode errors include context: `log.Printf("WebhookHandler: failed to decode request: %v", err)`
- Fatal errors in `main.go` use `log.Fatalf`
- `errors.Is()` used for sentinel error comparison (e.g., `http.ErrServerClosed`)
- String matching used for SQLite constraint errors: `strings.Contains(err.Error(), "UNIQUE")`
**TypeScript Patterns:**
- API errors throw with HTTP status: `throw new Error(\`HTTP ${res.status}\`)`
- Catch blocks use `console.error` for logging
- Error state stored in hook state: `setError(e instanceof Error ? e.message : 'Failed to fetch updates')`
- Optimistic updates used for tag assignment (update UI first, then call API)
## Logging
**Framework:** Go standard `log` package
**Patterns:**
- Startup messages: `log.Printf("Listening on :%s", port)`
- Warnings: `log.Println("WARNING: WEBHOOK_SECRET not set ...")`
- Request logging on success: `log.Printf("Update received: %s (%s)", event.Image, event.Status)`
- Error logging before HTTP error response: `log.Printf("WebhookHandler: failed to store event: %v", err)`
- Handler name prefixed to log messages: `"WebhookHandler: ..."`, `"UpdatesHandler: ..."`
**Frontend:** `console.error` for API failures, no structured logging
## Comments
**When to Comment:**
- Comments are sparse in the Go codebase
- Handler functions have short doc comments describing the routes they handle:
```go
// TagsHandler handles GET /api/tags and POST /api/tags
// TagByIDHandler handles DELETE /api/tags/{id}
// TagAssignmentHandler handles PUT /api/tag-assignments and DELETE /api/tag-assignments
```
- Inline comments used for non-obvious behavior: `// Migration: add acknowledged_at to existing databases`
- No JSDoc/TSDoc in the frontend codebase
## Function Design
**Go Handler Pattern:**
- Each handler is a standalone `func(http.ResponseWriter, *http.Request)`
- Method checking done at the top of each handler (not via middleware)
- Multi-method handlers use `switch r.Method`
- URL path parameters extracted via `strings.TrimPrefix`
- Request bodies decoded with `json.NewDecoder(r.Body).Decode(&target)`
- Responses written with `json.NewEncoder(w).Encode(data)` or `w.WriteHeader(status)`
- Mutex (`mu`) used around write operations to SQLite
**TypeScript Hook Pattern:**
- Custom hooks return object with state and action functions
- `useCallback` wraps all action functions
- `useEffect` for side effects (polling, initial fetch)
- State updates use functional form: `setUpdates(prev => { ... })`
## Module Design
**Go Exports:**
- Single package `diunwebhook` exports all types and handler functions
- No barrel files; single source file `diunwebhook.go` contains everything
- Test helpers exposed via `export_test.go` (only visible to `_test` packages)
**TypeScript Exports:**
- Named exports for all components, hooks, and utilities
- Default export only for the root `App` component (`export default function App()`)
- Type exports use `export interface` or `export type`
- `@/components/ui/` contains shadcn primitives (`badge.tsx`, `button.tsx`, etc.)
## Git Commit Message Conventions
**Format:** Conventional Commits with bold markdown formatting
**Pattern:** `**<type>(<scope>):** <description>`
**Types observed:**
- `feat` - new features
- `fix` - bug fixes
- `docs` - documentation changes
- `chore` - maintenance tasks (deps, config)
- `refactor` - code restructuring
- `style` - UI/styling changes
- `test` - test additions
**Scopes observed:** `docs`, `compose`, `webhook`, `ci`, `ui`, `main`, `errors`, `sql`, `api`, `deps`, `stats`
**Examples:**
```
**feat(webhook):** add `WEBHOOK_SECRET` for token authentication support
**fix(ci):** improve version bump script for robustness and compatibility
**docs:** expand `index.md` with architecture, quick start, and tech stack
**chore(docs):** add `.gitignore` for `docs` and introduce `bun.lock` file
```
**Multi-change commits:** Use bullet list with each item prefixed by `- **type(scope):**`
---
*Convention analysis: 2026-03-23*