{
  "id": "com.lattice.reading",
  "name": "Reading Log",
  "icon": "📚",
  "color": "#9d620b",
  "description": "Track books, shelves, ratings and reading dates in Goodreads export format.",
  "provenance": "Goodreads library CSV export. Verified 2026-10-14: https://www.goodreads.com/assets/sample_export.csv (official import template); https://www.goodreads.com/topic/show/419981-csv-import-export-format (export shelf semantics); https://example.invalid/resource (public actual export, headers and YYYY/MM/DD values). Adopted Book Id, Title, Author, ISBN, ISBN13, My Rating, Average Rating, Number of Pages, Date Read, Date Added, Bookshelves, Exclusive Shelf, My Review, Read Count as snake_case columns. Export dates and ISBN wrappers are preserved; blank page counts become NULL. The fixture selects the historical three default shelves; custom shelves and later additions are outside this subset. Events/listeners are fixture actions, not Goodreads webhooks.",
  "requested_permissions": {
    "storage": [
      "sql"
    ],
    "network": {
      "allowlist": []
    },
    "events": {
      "book-added": {
        "description": "A book was added.",
        "schema": {
          "type": "object",
          "properties": {
            "book_id": {
              "type": "integer",
              "description": "Goodreads edition ID."
            },
            "title": {
              "type": "string",
              "description": "Book title."
            },
            "author": {
              "type": "string",
              "description": "Author display name."
            },
            "isbn": {
              "type": "string",
              "description": "ISBN with spreadsheet wrapper, e.g. =\"0140328726\"; empty or =\"\" means unknown."
            },
            "isbn13": {
              "type": "string",
              "description": "ISBN13 with spreadsheet wrapper, e.g. =\"9780140328721\"; empty or =\"\" means unknown."
            },
            "my_rating": {
              "type": "integer",
              "description": "Star rating, 1–5; 0 means unrated.",
              "minimum": 0,
              "maximum": 5
            },
            "average_rating": {
              "type": "number",
              "description": "Average reader rating, 0–5 stars.",
              "minimum": 0,
              "maximum": 5
            },
            "number_of_pages": {
              "type": [
                "integer",
                "null"
              ],
              "description": "Page count; null means unknown.",
              "minimum": 0
            },
            "date_read": {
              "type": "string",
              "description": "Finish date, YYYY/MM/DD; empty means unrecorded.",
              "pattern": "^(|\\d{4}/\\d{2}/\\d{2})$"
            },
            "date_added": {
              "type": "string",
              "description": "Date added, YYYY/MM/DD; empty means unrecorded.",
              "pattern": "^(|\\d{4}/\\d{2}/\\d{2})$"
            },
            "bookshelves": {
              "type": "string",
              "description": "Comma-separated shelf names; empty means none."
            },
            "exclusive_shelf": {
              "type": "string",
              "description": "Current reading shelf.",
              "enum": [
                "to-read",
                "currently-reading",
                "read"
              ]
            },
            "my_review": {
              "type": "string",
              "description": "Review text; empty means none."
            },
            "read_count": {
              "type": "integer",
              "description": "Number of readings, including rereads.",
              "minimum": 0
            }
          },
          "required": [
            "book_id",
            "title",
            "author"
          ],
          "additionalProperties": false
        }
      },
      "reading-started": {
        "description": "A book moved to currently-reading.",
        "schema": {
          "type": "object",
          "properties": {
            "book_id": {
              "type": "integer",
              "description": "Goodreads edition ID."
            },
            "title": {
              "type": "string",
              "description": "Book title."
            },
            "author": {
              "type": "string",
              "description": "Author display name."
            },
            "exclusive_shelf": {
              "type": "string",
              "description": "Current reading shelf.",
              "enum": [
                "to-read",
                "currently-reading",
                "read"
              ],
              "const": "currently-reading"
            }
          },
          "required": [
            "book_id",
            "title",
            "exclusive_shelf"
          ],
          "additionalProperties": false
        }
      },
      "book-finished": {
        "description": "A book was marked read with a finish date.",
        "schema": {
          "type": "object",
          "properties": {
            "book_id": {
              "type": "integer",
              "description": "Goodreads edition ID."
            },
            "title": {
              "type": "string",
              "description": "Book title."
            },
            "author": {
              "type": "string",
              "description": "Author display name."
            },
            "my_rating": {
              "type": "integer",
              "description": "Star rating, 1–5; 0 means unrated.",
              "minimum": 0,
              "maximum": 5
            },
            "read_count": {
              "type": "integer",
              "description": "Number of readings, including rereads.",
              "minimum": 0
            },
            "exclusive_shelf": {
              "type": "string",
              "description": "Current reading shelf.",
              "enum": [
                "to-read",
                "currently-reading",
                "read"
              ],
              "const": "read"
            },
            "date_read": {
              "type": "string",
              "description": "Finish date, YYYY/MM/DD.",
              "pattern": "^\\d{4}/\\d{2}/\\d{2}$"
            }
          },
          "required": [
            "book_id",
            "title",
            "exclusive_shelf",
            "date_read"
          ],
          "additionalProperties": false
        }
      },
      "book-rated": {
        "description": "A book rating was set or cleared.",
        "schema": {
          "type": "object",
          "properties": {
            "book_id": {
              "type": "integer",
              "description": "Goodreads edition ID."
            },
            "title": {
              "type": "string",
              "description": "Book title."
            },
            "author": {
              "type": "string",
              "description": "Author display name."
            },
            "my_rating": {
              "type": "integer",
              "description": "Star rating, 1–5; 0 means unrated.",
              "minimum": 0,
              "maximum": 5
            }
          },
          "required": [
            "book_id",
            "title",
            "my_rating"
          ],
          "additionalProperties": false
        }
      }
    },
    "listeners": {
      "add-book": {
        "description": "Add a book if its Goodreads edition ID is absent.",
        "schema": {
          "type": "object",
          "properties": {
            "book_id": {
              "type": "integer",
              "description": "Goodreads edition ID."
            },
            "title": {
              "type": "string",
              "description": "Book title."
            },
            "author": {
              "type": "string",
              "description": "Author display name."
            },
            "isbn": {
              "type": "string",
              "description": "ISBN with wrapper, e.g. =\"0140328726\"; omitted, empty or =\"\" means unknown."
            },
            "isbn13": {
              "type": "string",
              "description": "ISBN13 with wrapper, e.g. =\"9780140328721\"; omitted, empty or =\"\" means unknown."
            },
            "my_rating": {
              "type": "integer",
              "description": "Star rating, 1–5; 0 means unrated; omitted defaults to 0.",
              "minimum": 0,
              "maximum": 5
            },
            "average_rating": {
              "type": "number",
              "description": "Average reader rating, 0–5 stars; omitted defaults to 0.",
              "minimum": 0,
              "maximum": 5
            },
            "number_of_pages": {
              "type": [
                "integer",
                "null"
              ],
              "description": "Page count; omitted or null means unknown.",
              "minimum": 0
            },
            "date_read": {
              "type": "string",
              "description": "Finish date, YYYY/MM/DD; omitted or empty means unrecorded.",
              "pattern": "^(|\\d{4}/\\d{2}/\\d{2})$"
            },
            "date_added": {
              "type": "string",
              "description": "Date added, YYYY/MM/DD; omitted or empty means unrecorded.",
              "pattern": "^(|\\d{4}/\\d{2}/\\d{2})$"
            },
            "bookshelves": {
              "type": "string",
              "description": "Comma-separated shelf names; omitted or empty means none."
            },
            "exclusive_shelf": {
              "type": "string",
              "description": "Current reading shelf; omitted defaults to to-read.",
              "enum": [
                "to-read",
                "currently-reading",
                "read"
              ]
            },
            "my_review": {
              "type": "string",
              "description": "Review text; omitted or empty means none."
            },
            "read_count": {
              "type": "integer",
              "description": "Number of readings, including rereads; omitted defaults to 0.",
              "minimum": 0
            }
          },
          "required": [
            "book_id",
            "title",
            "author"
          ],
          "additionalProperties": false
        }
      }
    }
  },
  "x-effects": {
    "add-book": {
      "table": "books",
      "emits": "book-added"
    }
  },
  "source": {
    "assets": [
      "index.html",
      "app.js",
      "app.css",
      "ui.css",
      "emits.js",
      "listens.js"
    ]
  }
}