[Hosted][Design] The add-on seam: the neutral hooks, and how an add-on plugs in #1142

Open
opened 2026-10-12 23:26:10 +00:00 by claude-bot · 0 comments
Collaborator

A design record to be read and agreed by the owner before anything is built, because the add-on depends on it across every later release.

To settle

  • The list of hooks and their exact questions and answers: creating, un-archiving and accepting a campaign; redeeming an invite; starting a recording (bot → backend, so the bot contract); process_audio, the LLM fan-out and each on-demand generator; what a refusal looks like to the user and to the bot ({"detail": …}), and what a self-hosted server answers (always yes).
  • What the app tells the add-on: usage events from session_usage, campaign lifecycle events (created, archived, owner changed, deleted), so the add-on never reads the app's tables behind its back.
  • How an add-on is discovered and loaded: its provider (today PROVIDERS is a fixed dict in entitlement_service.py), routers, Celery tasks, settings, and its Alembic migrations in their own version location so the public history never mentions billing.
  • The frontend extension point: pages, account-menu and Admin entries, and the in-app states a refusal draws ("this campaign is read-only", out of credits), with the public build drawing none of the billing pages.
  • What moves out of the public app (see the build issue), and what stays because self-hosters use it (archive, read-only, usage records, own AI keys).
  • Versioning: how the add-on declares which app versions it works with, as the bot does with BOT_CONTRACT_VERSION.

Waits on Q175 to Q180 only where an answer changes a hook (the trial and the mixed-AI case do).

Part of the hosted service (#642). Decision of 2026-10-12: the public app carries only neutral hooks; a private add-on carries the business.

A design record to be read and agreed by the owner before anything is built, because the add-on depends on it across every later release. **To settle** - The list of hooks and their exact questions and answers: creating, un-archiving and accepting a campaign; redeeming an invite; starting a recording (bot → backend, so the bot contract); `process_audio`, the LLM fan-out and each on-demand generator; what a refusal looks like to the user and to the bot (`{"detail": …}`), and what a self-hosted server answers (always yes). - What the app tells the add-on: usage events from `session_usage`, campaign lifecycle events (created, archived, owner changed, deleted), so the add-on never reads the app's tables behind its back. - How an add-on is discovered and loaded: its provider (today `PROVIDERS` is a fixed dict in `entitlement_service.py`), routers, Celery tasks, settings, and its Alembic migrations in their own version location so the public history never mentions billing. - The frontend extension point: pages, account-menu and Admin entries, and the in-app states a refusal draws ("this campaign is read-only", out of credits), with the public build drawing none of the billing pages. - What moves out of the public app (see the build issue), and what stays because self-hosters use it (archive, read-only, usage records, own AI keys). - Versioning: how the add-on declares which app versions it works with, as the bot does with `BOT_CONTRACT_VERSION`. **Waits on** Q175 to Q180 only where an answer changes a hook (the trial and the mixed-AI case do). Part of the hosted service (#642). Decision of 2026-10-12: the public app carries only neutral hooks; a private add-on carries the business.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/Quest-Board#1142
No description provided.