feat: scaffold auth prototype and docs

This commit is contained in:
Ruidy 2025-09-19 23:10:27 +02:00
parent 4d6e35c4cb
commit d45e6f4f07
No known key found for this signature in database
GPG key ID: 705C24D202990805
5 changed files with 160 additions and 2 deletions

35
AGENTS.md Normal file
View file

@ -0,0 +1,35 @@
# Repository Guidelines
## Project Structure & Module Organization
Keep the single Go module defined in `go.mod`. Server entry lives in `main.go`, while `index.html` and `in.html` provide public and authenticated templates beside it. Use `tmp/` strictly for generated artifacts (e.g., binaries, logs); never commit its contents. When expanding the app, group domain-specific handlers and helpers in packages under the repo root.
## Approved Technologies & Dependencies
Favor the Go standard library for routing, templating, crypto, and storage. The only pre-approved third-party package is `github.com/go-chi/chi/v5` for HTTP routing if the standard mux becomes limiting. Front-end interactivity must rely on htmx and Alpine.js with semantic HTML, and Pico.css is the accepted design system. Embed templates, scripts, and styles into the binary using Go's `embed` package so deployments stay self-contained. Avoid introducing other dependencies without prior discussion and an update to this document.
## Authentication Flow Requirements
Implement email/password authentication with secure password hashing, CSRF protection, and clear failure states. Use semantic forms enhanced by htmx for progressive enhancement and Alpine.js for lightweight client behavior. Persist session state on the server, prefer HTTP-only cookies, and render authenticated views without leaking sensitive data.
## Build, Test, and Development Commands
- `go run .` starts the dev server on <http://localhost:8000>.
- `go build -o tmp/auth` emits a clean binary for manual testing.
- After every change, run `gofmt -w ./...`, `go vet ./...`, and `go test ./...` to ensure formatting, static checks, and regression coverage before you push.
## Coding Style & Naming Conventions
Trust `gofmt`; no manual formatting tweaks. Use CamelCase for exported Go identifiers and snake_case for static assets. Keep handlers slim, factor reusable logic into helpers, and add brief comments only when intent is not obvious. Template IDs and Alpine component names should describe their role (e.g., `login_form`).
## Testing Guidelines
Adopt Gos `testing` package with table-driven cases. Name files `<feature>_test.go`, colocated with the code under test. Run `go test ./...` (and `go test -cover ./...` for major features) before opening a PR, ensuring new branches maintain or raise coverage.
## Commit & Pull Request Guidelines
Follow Conventional Commits (`feat:`, `fix:`, `chore:`). PRs must summarize the change, link relevant issues, include manual verification notes, and attach screenshots or screen recordings for UI updates.
## Living Document
This guide evolves with the project. Whenever you add a tool, workflow, or architectural rule, update this section so future contributors inherit the collective knowledge.

36
AUTH_PLAN.md Normal file
View file

@ -0,0 +1,36 @@
# Authentication Implementation Plan
## Project Restructure
- Move the entrypoint to `cmd/server/main.go` and create `internal/server` for router, middleware, and session bootstrap logic.
- Add `internal/auth` for credential hashing, validation helpers, and user/session abstractions.
- Relocate templates and static assets to `web/` and embed them with `embed.FS` so the binary stays self-contained.
## Routing & Middleware
- Adopt `github.com/go-chi/chi/v5` with recovery, request logging, and session-loading middleware.
- Maintain an in-memory session store backed by HTTP-only cookies; compare secrets with `crypto/subtle` and rotate session IDs on login/logout.
## Authentication Core
- Implement password hashing with per-user random salts (`crypto/rand`, `sha256`) and base64 encoding for storage.
- Define a user repository interface seeded with an in-memory implementation until persistence is added.
- Generate CSRF tokens tied to session state and validate them for every mutating request.
## Templates & Frontend
- Replace static HTML with `html/template` views built on semantic markup and Pico.css styling.
- Enhance forms using htmx for progressive submission and Alpine.js for light client interactivity (loading states, error visibility).
- Serve embedded assets via helper endpoints or template functions using the embedded filesystem.
## Handlers & Flows
- Create `GET /signin`, `POST /signin`, `GET /signup`, `POST /signup`, `POST /signout`, and protected dashboard routes.
- Return precise HTTP status codes and htmx-compatible fragments for validation errors.
- Guard authenticated routes with middleware that checks session validity before rendering protected pages.
## Testing Strategy
- Cover hashing and CSRF helpers with table-driven unit tests.
- Use `net/http/httptest` to verify happy-path login, signup, logout, invalid credential handling, CSRF failures, and session persistence.
- Run `go test -cover ./...` to ensure the new logic maintains regression coverage.

18
in.html Normal file
View file

@ -0,0 +1,18 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>auth test</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
/>
</head>
<body>
<main class="container">
<h1>Logged in</h1>
<p>You are logged in. This is a test page for the authentication</p>
</main>
</body>
</html>

32
index.html Normal file
View file

@ -0,0 +1,32 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>auth test</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
/>
</head>
<body>
<main class="container">
<h1>Login</h1>
<p>
This is a test page for the authentication system. Please log in to
continue.
</p>
<form method="post" action="/login">
<input
type="email"
id="email"
placeholder="Enter your email"
required
autofocus
/>
<input type="password" id="password" placeholder="password" required />
<button type="submit">Login</button>
</form>
</main>
</body>
</html>

41
main.go
View file

@ -1,7 +1,44 @@
package main
import "fmt"
import (
"log"
"net/http"
)
var loggedIn = false
func main() {
fmt.Println("Hello, World!")
mux := http.NewServeMux()
mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
})
mux.HandleFunc("GET /in", func(w http.ResponseWriter, r *http.Request) {
if loggedIn {
http.ServeFile(w, r, "in.html")
} else {
w.Header().Add("Content-Type", "text/html")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(`
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css" />
</head>
<body>
<main class="container">
<h1>Unauthorized</h1> <a href='/' role='button'> Back to safety </a>
</main>
</body>
`))
}
})
mux.HandleFunc("POST /login", func(w http.ResponseWriter, r *http.Request) {
log.Println("Login request received")
loggedIn = true
http.Redirect(w, r, "/in", http.StatusSeeOther)
})
log.Println("Starting server on http://localhost:8000")
http.ListenAndServe(":8000", mux)
}