Run artifact

workspace/targets/ReadingList/blueprint/DATABASE.md

DATABASE: Book Persistence

FieldValue
Version20260815 V1
DescriptionDefines the SQLite persistence contract for ordered reading-list books.
Depends OnARCHITECTURE.md
Providesbook_store.add, book_store.list_ordered, book_store.remove, books_table
Consumesapplication_factory

Access Patterns

CallerOperationStoreInterface
Book creation workflowAdd a submitted title and authorbooksBookStore.add(title, author)
Ordered-list workflowRead all booksbooksBookStore.list_ordered()
Book-removal workflowDelete a selected bookbooksBookStore.remove(book_id)

Persistence Interfaces

StorePublic interfaceModuleAllowed callersNotes
SQLite books tableBookStore.add(title, author) -> Bookapp.persistenceApplication workflowsPersists one book.
SQLite books tableBookStore.list_ordered() -> list[Book]app.persistenceApplication workflowsReturns rows in insertion order.
SQLite books tableBookStore.remove(book_id) -> boolapp.persistenceApplication workflowsRemoves the selected row and reports whether it existed.

Schema

The books table contains:

The primary key is monotonically assigned by SQLite and is used to preserve insertion order. The database must reject null title or author values. Application validation additionally rejects empty submitted values.

Configuration

The application factory supplies the database location through Flask configuration. Tests may provide an isolated temporary path or an in-memory database. Connections are scoped to the application context and closed after use.

Migrations and Initialization

Application startup creates the books table when it does not exist. Initialization is idempotent and must not delete existing rows.

Programmatic Acceptance

=== AC database-add-readback ===
Intent: A book added through the persistence interface can be read back with the submitted fields.

from app import create_app from app.persistence import get_book_store

title = "The Dispossessed" author = "Ursula K. Le Guin" application = create_app({"TESTING": True, "DATABASE": ":memory:"})

with application.app_context(): store = get_book_store() created = store.add(title, author) books = store.list_ordered()

assert len(books) == 1 assert books[0].id == created.id assert books[0].title == title assert books[0].author == author === END AC database-add-readback ===

=== AC database-order ===
Intent: Ordered reads preserve the order in which books were added.

from app import create_app from app.persistence import get_book_store

first_title = "A" first_author = "Author A" second_title = "B" second_author = "Author B" application = create_app({"TESTING": True, "DATABASE": ":memory:"})

with application.app_context(): store = get_book_store() store.add(first_title, first_author) store.add(second_title, second_author) books = store.list_ordered()

assert [book.title for book in books] == [first_title, second_title] assert [book.author for book in books] == [first_author, second_author] === END AC database-order ===

=== AC database-remove ===
Intent: Removing an existing book makes it absent from a subsequent persistence read.

from app import create_app from app.persistence import get_book_store

title = "To Remove" author = "Author" application = create_app({"TESTING": True, "DATABASE": ":memory:"})

with application.app_context(): store = get_book_store() created = store.add(title, author) removed = store.remove(created.id) books = store.list_ordered()

assert removed is True assert books == [] === END AC database-remove ===

=== AC database-empty ===
Intent: A new database returns an empty ordered collection.

from app import create_app from app.persistence import get_book_store

application = create_app({"TESTING": True, "DATABASE": ":memory:"})

with application.app_context(): books = get_book_store().list_ordered()

assert books == [] === END AC database-empty ===

User Acceptance

Guardrails