package docs import ( "encoding/json" "bookhoard/internal/handlers" ) // Schema pins the machine-checkable contract for one route. The drift gate // (drift_test.go) validates every frontmatter'd doc against the entry for its // "METHOD path" key. // // MAINTENANCE CONTRACT: every doc with frontmatter MUST have a registry // entry, and every new/changed route that ships a frontmatter'd doc updates // its entry in the same commit. The gate fails loudly on a missing entry — // that is the discipline, not an inconvenience. // // Request: the struct the handler Binds into (nil for bodyless routes). // - example-request is decoded with unknown fields DISALLOWED (typo guard) // - fields whose validate tag contains "required" must appear in the // example (staleness guard) // // Response: what the handler passes to c.JSON. // - struct / slice of struct: marshaled and its TOP-LEVEL key set compared // against example-response in both directions // - json.RawMessage: hand-built map responses pin their key set as a // sample; promote to a struct when the endpoint is next touched // - zero value (Schema{}): no JSON body expected (e.g. 204) — the doc must // not carry an example-response block type Schema struct { Request any Response any } // Schemas is keyed by "METHOD path" in Echo syntax. Sample values inside // RawMessage pins use empty strings / zero values — only the KEY SET is // checked, never the values. var Schemas = map[string]Schema{ // --- collections (pilot area) --- "POST /api/collections": { Request: handlers.CreateCollectionRequest{}, Response: json.RawMessage(`{ "id": "", "user_id": "", "name": "", "description": "", "color": "", "icon": "", "collection_type": "", "auto_assign_rules": null, "view_settings": {}, "book_count": 0, "created_at": "" }`), }, "GET /api/collections": { Response: struct { Collections []handlers.CollectionSummary `json:"collections"` Total int `json:"total"` }{}, }, "GET /api/collections/:id": { Response: json.RawMessage(`{ "id": "", "user_id": "", "name": "", "description": "", "color": "", "icon": "", "auto_assign_rules": null, "view_settings": {}, "books": [], "book_count": 0, "is_smart": false, "up_next": [], "created_at": "" }`), }, "PUT /api/collections/:id": { Request: handlers.UpdateCollectionRequest{}, Response: json.RawMessage(`{ "id": "", "user_id": "", "name": "", "description": "", "color": "", "icon": "", "auto_assign_rules": null, "view_settings": {}, "created_at": "" }`), }, "DELETE /api/collections/:id": {}, }