We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Data Leaks

An endpoint can pass every authorization check and still reveal more data than it should. Imagine an online bookstore that sends its full inventory records to every shopper:

func booksHandler(responseWriter http.ResponseWriter, request *http.Request) {
    books, err := store.ListAllBooks(request.Context())
    if err != nil {
        http.Error(responseWriter, "Something went wrong", http.StatusInternalServerError)
        return
    }
    _ = json.NewEncoder(responseWriter).Encode(map[string]any{"books": books})
}

Those records might include supplier costs, unpublished titles, acquisition notes, and internal audit fields. The storefront didn't need any of that.

Maybe the endpoint was safe when the table it was reading from only contained public fields. But as the data model grows, every endpoint that returns the whole record inherits its new private data. Oopsie.

Explicit Response Shapes

You should explicitly control what crosses the server-to-client boundary! A typed response shape gives you a stable public contract that doesn't grow just because the database model does:

type bookResponse struct {
    ID     int64  `json:"id"`
    Title  string `json:"title"`
    Author string `json:"author"`
}

func toBookResponse(book Book) bookResponse {
    return bookResponse{
        ID:     book.ID,
        Title:  book.Title,
        Author: book.Author,
    }
}

Return the fields the client is allowed to see, not the value you happen to store in your database.

Assignment

Bearly Secure's public product and customer order APIs return complete stored models. Return explicit public response shapes instead.

With Bearly Secure still running, run and submit the CLI tests from the project root.