halkyon/docs/adr/0022-no-hand-off-and-no-connector.md
Tizian 「ティツィアーン」 c48d423619
docs(adr): ADR 0021 accepted, the assistant's boundaries (D7–D30)
The developer's decisions of 25 Oct, reviewing ADR 0021 whole:

- What an assistant may see and do (D7–D12): the scope of each question
  (the parts ticked, the studyset, its tree, the library), looked up
  through read-only tools the app answers on the device; private
  studysets out of a wider scope unless switched on, and a warning
  whenever one's content would go to a remote model, Lumo included, as
  no provider keeps a question confidential while its model answers;
  changes only as drafts; progress never; text first, an image when
  ticked or asked for.
- What it keeps, does and where it lives (D13–D18): conversations kept
  sealed with the person's own key; four features (questions about what
  is open, cards from text, explaining a miss, checking a written
  answer); grants and limits in halkyon_base, the adapters in a package
  of their own (halkyon_llm, BSD-3-Clause); the proposal's points 4–8
  and 10 as written; the warning once per studyset and assistant; built
  for v0.21.0.
- Sign-ups and operators (D19–D26): SIGN_UP open, approval or closed;
  the first operator by SQL, others named in the app; suspending an
  approved account; a wait screen with a matching code the operator
  checks with the person; 14 days, 10 waiting.
- What people are told and what never goes (D27–D30): the app and a
  privacy page of each instance's own; others' posts only with their
  author's switch, a copy's licence being its agreement; an opaque ID
  per person for the provider.

ADR 0022 and Learn's AGENTS.md now point to it as accepted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 07:17:04 +01:00

77 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR 0022: No hand-off and no connector
- **Status:** decided 23 Oct 2026, by the developer (D1–D3 below); built for v0.19.0
(build 22).
- **Supersedes:** ADR 0006 (Claude reads studysets through a connector on the instance),
and the hand-off to an AI assistant outside the app (decided 10 and 14 Oct 2026, Learn's
`AGENTS.md`).
- **Followed by:** ADR 0021 (an assistant on the instance, on its operator's keys),
accepted 25 Oct 2026.
## Context
Since 10 Oct a question asked from the app could leave it in two ways, both through the
person's own subscription, as Halkyon called no language model with an API key: the
hand-off opened the chosen assistant's new conversation (Lumo by default, ChatGPT,
Claude, …) with the question and the chosen parts written in, for the person to send; and
Claude's apps read the person's studysets through the instance's connector (ADR 0006: MCP
at `/mcp` with its own OAuth, connected with a code from Settings › Assistant › Connect
Claude). Beside them, the same field searched the web.
ADR 0021 proposes an assistant inside the app on an instance whose operator pays for it:
several providers on the operator's keys, granted per person, with limits and statistics,
and personal keys where the operator allows them. The developer asked on 23 Oct to "drop
the Assistant part that just opens the assistant outside of the app, but let's keep the
web open part", or else decide how the instance's own assistant and opening one's own
outside the app go together.
## Decisions (23 Oct 2026, the developer's)
- **D1 The hand-off goes now** (over keeping it until the instance's assistant comes,
which was recommended): until then the field searches the web only.
- **D2 The connector goes too** (over keeping it, which was recommended): an instance has
one way to an assistant, its operator's (ADR 0021), and nothing else on it reads
people's content for a language model.
- **D3 In v0.19.0, the app and the server together** (over releasing v0.19.0 first and
taking the server's part out with the next raise of `minimumAppBuild`, which was
recommended): build 22 raises `minimumAppBuild` to 22 anyway, so no app that calls the
connector's endpoints can use the instance after it, and nothing needs to stay for
older apps.
## What goes, and what stays
1. **In the app:** the assistants a question opened in (`AiAssistant`, `AssistantHandOff`),
the switch at the field's start between them and the web (`assistantTarget`), Settings'
choice of assistant, Connect Claude with its route, cubit, repository and gateway, and
their texts. A device's settings file from before keeps the old keys (`aiAssistant`,
`customAssistantUrl`, `assistantTarget`) until the next change of a setting writes it
anew without them; nothing reads them.
2. **On the server:** `lib/src/assistant/` (the MCP endpoint, its OAuth pages and metadata,
the five tools, connect codes, tokens), `AssistantEndpoint`, the daily forgetting of
the connector's codes and tokens, their lines in Learn's deletion hook,
`instance.info().assistantConnectorUrl` (nullable, so an older app reads it as none),
and Caddy's forwarding of `/mcp`, `/oauth/*` and `/.well-known/oauth-*`. A migration
drops the five tables (`assistant_client`, `assistant_connect_code`,
`assistant_connection`, `assistant_grant`, `assistant_token`) with every connection,
code and token in them: from the deploy on, a connected Claude gets no answer, and
people remove the connector in Claude's settings.
3. **Stays:** the field (`AssistantBar` on Home, `AssistantButton` in the Library, on a
studyset and while studying), off unless the person turns it on in Settings, its chips
of what the question is about (those a web search takes: a card's front, back, hints
and explanation, never a studyset's name or description), and the web search through
the engine chosen in Settings, or Android's own search.
## Consequences
- Until an instance offers ADR 0021's assistant, its people ask no language model from the
app. learn.halkyon.eu, a public instance, offers none (ADR 0021: public instances leave
the assistant unset).
- The instance reads payloads in one place fewer (ADR 0019's context named four).
- **The deploy breaks the rule that migrations keep the old server working until the
switch**, for the minute between the maintenance run and the new server: the old one
then answers the connector's calls with errors, and an account deleted meanwhile (by
its owner, or the pruning) fails and is deleted when asked again, as the old server's
deletion hook still deletes from the connector's tables. Keeping the tables a release
longer would keep the rule, for codes and tokens nothing reads; since build 22 raises
`minimumAppBuild` (D3), no released app syncs with that server by then.
- The privacy page (website repository) drops the connector and the hand-off to Lumo.