{"openapi":"3.1.0","info":{"title":"PageCompass Delegated Reader API","version":"1.0.0","description":"Private, human-consented account API. It is NOT the public /agent/mcp recommendation gateway and does not auto-correct books or ranking.","x-pagecompass-agent-instructions":["Discover /.well-known/pagecompass-reader-agent.json and OAuth metadata before asking to connect.","A human, not the bot, logs in and authorizes an explicitly allowlisted assistant client.","Use the exact registered redirect_uri and OAuth resource parameter in BOTH authorization and token/refresh requests.","Do not use a public gateway bearer key, PageCompass session cookie, password, billing credentials or admin secret.","Default scopes: profile:read library:read quality:report profile:suggest.","Treat bot observations as unverified until independently corroborated. No admin/catalog/ranking access is exposed."]},"servers":[{"url":"https://pagecompass.onrender.com"}],"externalDocs":{"url":"https://pagecompass.onrender.com/development","description":"Human and bot integration guide"},"security":[{"readerOAuth":[]}],"paths":{"/agent/account/v1/me":{"get":{"summary":"Read the human's display name and reader ID","operationId":"readerMe","security":[{"readerOAuth":["profile:read"]}],"responses":{"200":{"description":"Reader identity (no email or administrative fields).","content":{"application/json":{"schema":{"type":"object","required":["id","display_name"],"properties":{"id":{"type":"string"},"display_name":{"type":"string"}}}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/agent/account/v1/profile":{"get":{"summary":"Read the approved reading preferences","operationId":"readerProfile","security":[{"readerOAuth":["profile:read"]}],"responses":{"200":{"description":"GET uses snake_case keys.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReaderProfile"}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"patch":{"summary":"Directly edit favorites (normally OFF; prefer profile:suggest)","operationId":"editReaderProfile","security":[{"readerOAuth":["profile:write"]}],"description":"Admin-controlled PAGECOMPASS_AGENT_DIRECT_PROFILE_WRITES_ENABLED must equal true. Input uses camelCase, unlike read response.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectProfileEdit"}}}},"responses":{"200":{"description":"Updated reading preferences.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReaderProfile"}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/agent/account/v1/library":{"get":{"summary":"Read the human's saved catalog lists, not uploaded book content","operationId":"readerLibrary","security":[{"readerOAuth":["library:read"]}],"responses":{"200":{"description":"Reader's saved reading lists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReaderLibrary"}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/agent/account/v1/library/status":{"post":{"summary":"Update catalog book status (normally OFF)","operationId":"setReadingStatus","description":"Admin-controlled PAGECOMPASS_AGENT_LIBRARY_WRITES_ENABLED must equal true. Input status 'want' appears as output list 'interested'. No private file operations.","security":[{"readerOAuth":["library:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["book_id","status"],"properties":{"book_id":{"type":"string","minLength":1,"maxLength":160},"status":{"enum":["read","want","wishlist","rejected"]}}}}}},"responses":{"200":{"description":"Saved status.","content":{"application/json":{"schema":{"type":"object","required":["book_id","status"],"properties":{"book_id":{"type":"string","minLength":1,"maxLength":160},"status":{"type":"string"}}}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/agent/account/v1/quality-reports":{"post":{"summary":"Queue an evidence-only catalog, recommendation or site issue","operationId":"submitQualityReport","security":[{"readerOAuth":["quality:report"]}],"description":"201 created; 200 identical idempotent retry; 409 same key with changed body; 404 unknown catalog book. 100 reports/grant/day and 25 calls/min. No catalog, ranking or Chiropractor writes.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QualityReportInput"}}}},"responses":{"200":{"description":"Idempotent duplicate acknowledged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QualityReportAck"}}}},"201":{"description":"Report queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QualityReportAck"}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Catalog book ID not found.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Idempotency key reused for a different report.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"get":{"summary":"Read this grant's recent report statuses","operationId":"listQualityReports","security":[{"readerOAuth":["quality:report"]}],"responses":{"200":{"description":"At most 40 recent reports owned by the grant.","content":{"application/json":{"schema":{"type":"object","properties":{"reports":{"type":"array","items":{"type":"object"}}}}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/agent/account/v1/reading-setup-drafts":{"post":{"summary":"Propose structured reader dislikes and other starting preferences for human confirmation","operationId":"proposeReadingSetup","security":[{"readerOAuth":["profile:suggest"]}],"description":"No direct profile mutation. The reader reviews a full-profile, version-checked draft; an assistant must preserve existing approved values. Inferred assertions remain pending.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadingSetupDraftInput"}}}},"responses":{"201":{"description":"Pending draft, not applied to a reader profile.","content":{"application/json":{"schema":{"type":"object","required":["draft_id","status","review_url"],"properties":{"draft_id":{"type":"string"},"status":{"const":"pending"},"review_url":{"type":"string"}}}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Idempotency key conflict or profile version conflict.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/agent/account/v1/taste-proposals":{"post":{"summary":"Propose a preference for the human to approve","operationId":"proposeTaste","security":[{"readerOAuth":["profile:suggest"]}],"description":"No profile change on submission. Only positive favorites are supported; reader approves or rejects under Account. 40 proposals/grant/day and 12 calls/min.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TasteProposalInput"}}}},"responses":{"200":{"description":"Idempotent duplicate acknowledged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TasteProposalAck"}}}},"201":{"description":"Proposal queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TasteProposalAck"}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Idempotency key reused for a different proposal.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"get":{"summary":"Read this grant's recent proposals","operationId":"listTasteProposals","security":[{"readerOAuth":["profile:suggest"]}],"responses":{"200":{"description":"At most 40 recent proposals owned by the grant.","content":{"application/json":{"schema":{"type":"object","properties":{"proposals":{"type":"array","items":{"type":"object"}}}}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/agent/account/mcp":{"post":{"summary":"Stateless, bearer-protected JSON-RPC MCP tools","operationId":"readerMcp","description":"Protocol version 2025-06-18. Call initialize, tools/list, then tools/call; tools/list filters out scopes the human did not approve and disabled writes. JSON-RPC errors return HTTP 200; check error within JSON-RPC.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"const":"2.0"},"id":{},"method":{"type":"string"},"params":{"type":"object"}}}}}},"responses":{"200":{"description":"JSON-RPC result, including result.structuredContent for tools/call.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input. Body includes error string (not the public gateway error.code envelope).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Invalid, expired or revoked delegated bearer token.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Insufficient scope or feature disabled.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Submission quota or rate limit exceeded; honor Retry-After if present.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Temporary service unavailability; retry with backoff, retaining the idempotency key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"security":[{"readerOAuth":[]}]}}},"components":{"securitySchemes":{"readerOAuth":{"type":"oauth2","description":"Human-approved Authorization Code with mandatory PKCE S256 and RFC 8707 resource parameter. Exact HTTPS callbacks and static or restricted dynamic client registration.","flows":{"authorizationCode":{"authorizationUrl":"https://pagecompass.onrender.com/oauth/authorize","tokenUrl":"https://pagecompass.onrender.com/oauth/token","scopes":{"profile:read":"View your reading preferences and profile name","profile:write":"Update your favorite genres, authors, and reading moods","library:read":"View your saved books and reading status","library:write":"Add books to your lists or change their reading status","quality:report":"Report book, recommendation and site defects for review","profile:suggest":"Suggest reading preferences for your approval (never silently changes tastes)"}}}}},"schemas":{"ReaderProfile":{"type":"object","required":["favorite_genres","favorite_authors","reading_moods","taste_summary"],"properties":{"favorite_genres":{"type":"array","items":{"type":"string"}},"favorite_authors":{"type":"array","items":{"type":"string"}},"reading_moods":{"type":"array","items":{"type":"string"}},"taste_summary":{"type":["string","null"]},"reading_setup":{"anyOf":[{"$ref":"#/components/schemas/ReadingSetupProfile"},{"type":"null"}]},"reading_setup_version":{"type":"integer","minimum":0}}},"ReaderDislike":{"oneOf":[{"type":"object","additionalProperties":false,"required":["kind","code","severity"],"properties":{"kind":{"const":"typed"},"code":{"enum":["sprawling_cast","tedious_pacing","needlessly_confusing","dense_prose","romance_heavy","graphic_violence","bleak_ending"]},"severity":{"enum":["soft","hard"]}}},{"type":"object","additionalProperties":false,"required":["kind","text","severity"],"properties":{"kind":{"const":"custom"},"text":{"type":"string","minLength":1,"maxLength":120},"severity":{"enum":["soft","hard"]}}}]},"ReadingSetupProfile":{"type":"object","additionalProperties":false,"required":["genres","enjoyed_books","favorite_authors","interests","soft_avoidances","hard_exclusions"],"properties":{"genres":{"type":"array","maxItems":3,"items":{"type":"string","maxLength":80}},"enjoyed_books":{"type":"array","maxItems":5,"items":{"type":"object","additionalProperties":false,"required":["title"],"properties":{"title":{"type":"string","maxLength":160},"author":{"type":"string","maxLength":120}}}},"favorite_authors":{"type":"array","maxItems":5,"items":{"type":"string","maxLength":120}},"interests":{"type":"array","maxItems":5,"items":{"type":"string","maxLength":100}},"soft_avoidances":{"type":"array","maxItems":5,"items":{"type":"string","maxLength":150}},"hard_exclusions":{"type":"array","maxItems":5,"items":{"type":"string","maxLength":150}},"dislikes":{"type":"array","maxItems":12,"items":{"$ref":"#/components/schemas/ReaderDislike"}}}},"ReadingSetupDraftInput":{"type":"object","additionalProperties":false,"required":["profile","evidence_kind","idempotency_key"],"properties":{"profile":{"$ref":"#/components/schemas/ReadingSetupProfile"},"evidence_kind":{"enum":["reader_explicit","assistant_inferred"]},"idempotency_key":{"type":"string","minLength":16,"maxLength":100,"pattern":"^[A-Za-z0-9._:-]+$"}}},"DirectProfileEdit":{"type":"object","additionalProperties":false,"properties":{"favoriteGenres":{"type":"array","maxItems":15,"items":{"type":"string"}},"favoriteAuthors":{"type":"array","maxItems":15,"items":{"type":"string"}},"readingMoods":{"type":"array","maxItems":15,"items":{"type":"string"}}},"minProperties":1},"ReaderLibrary":{"type":"object","required":["read","interested","wishlist","currently_reading"],"properties":{"read":{"type":"array","items":{"type":"object","required":["book_id","title","author"],"properties":{"book_id":{"type":"string"},"title":{"type":"string"},"author":{"type":"string"}}}},"interested":{"type":"array","items":{"type":"object","required":["book_id","title","author"],"properties":{"book_id":{"type":"string"},"title":{"type":"string"},"author":{"type":"string"}}}},"wishlist":{"type":"array","items":{"type":"object","required":["book_id","title","author"],"properties":{"book_id":{"type":"string"},"title":{"type":"string"},"author":{"type":"string"}}}},"currently_reading":{"type":"array","items":{"type":"object","required":["book_id","title","author"],"properties":{"book_id":{"type":"string"},"title":{"type":"string"},"author":{"type":"string"}}}}}},"QualityReportInput":{"oneOf":[{"type":"object","additionalProperties":false,"required":["category","reason_code","note","idempotency_key","book_id"],"properties":{"category":{"const":"catalog"},"book_id":{"type":"string","minLength":1,"maxLength":160},"reason_code":{"enum":["missing_cover","broken_cover","wrong_cover","wrong_author","wrong_genre","wrong_language","wrong_format","missing_description","wrong_description","duplicate_edition","incorrect_metadata","other"]},"note":{"type":"string","minLength":3,"maxLength":500},"idempotency_key":{"type":"string","minLength":16,"maxLength":100,"pattern":"^[A-Za-z0-9._:-]+$"}}},{"type":"object","additionalProperties":false,"required":["category","reason_code","note","idempotency_key","book_id","requested_constraint"],"properties":{"category":{"const":"recommendation"},"book_id":{"type":"string","minLength":1,"maxLength":160},"reason_code":{"enum":["violates_exclusion","wrong_genre","wrong_form","wrong_tone","too_dark","too_slow","too_long","too_short","inaccurate_explanation","irrelevant","other"]},"note":{"type":"string","minLength":3,"maxLength":500},"idempotency_key":{"type":"string","minLength":16,"maxLength":100,"pattern":"^[A-Za-z0-9._:-]+$"},"requested_constraint":{"type":"string","minLength":3,"maxLength":160},"gateway_session_id":{"type":"string","pattern":"^agent-[0-9a-f-]{36}$","maxLength":42},"displayed_slot":{"type":"integer","minimum":1,"maximum":10}}},{"type":"object","additionalProperties":false,"required":["category","reason_code","note","idempotency_key","page_path"],"properties":{"category":{"const":"site"},"page_path":{"type":"string","maxLength":200,"pattern":"^/(?!/)[A-Za-z0-9/_?&.=%-]*$"},"reason_code":{"enum":["broken_link","inaccurate_display","accessibility","api_error","user_interface","performance","other"]},"note":{"type":"string","minLength":3,"maxLength":500},"idempotency_key":{"type":"string","minLength":16,"maxLength":100,"pattern":"^[A-Za-z0-9._:-]+$"}}}]},"QualityReportAck":{"type":"object","required":["report_id","status","evidence_level","catalog_modified","ranking_modified"],"properties":{"report_id":{"type":"string"},"status":{"enum":["pending","accepted","dismissed","needs_evidence"]},"evidence_level":{"enum":["verified_catalog_gap","reported_unverified","contradicts_catalog"]},"next_step":{"type":"string"},"recommendation_refinement":{"type":["object","null"]},"catalog_modified":{"const":false},"ranking_modified":{"const":false}}},"TasteProposalInput":{"type":"object","additionalProperties":false,"required":["idempotency_key","dimension","value","polarity","evidence_kind","confidence","rationale"],"properties":{"idempotency_key":{"type":"string","minLength":16,"maxLength":100,"pattern":"^[A-Za-z0-9._:-]+$"},"dimension":{"enum":["favorite_genre","favorite_author","reading_mood"]},"value":{"type":"string","minLength":1,"maxLength":70},"polarity":{"const":"like"},"evidence_kind":{"enum":["reader_explicit","reader_inferred"]},"confidence":{"enum":["low","medium","high"]},"rationale":{"type":"string","minLength":3,"maxLength":300}}},"TasteProposalAck":{"type":"object","required":["proposal_id","status","applied_to_profile","next_step"],"properties":{"proposal_id":{"type":"string"},"status":{"enum":["pending","approved","rejected"]},"applied_to_profile":{"type":"boolean"},"next_step":{"type":"string"}}}}}}