docs(issue-62): add relay plan for AuthStorage->ModelRuntime migration

This commit is contained in:
Federico Jaramillo Martinez
2026-07-17 20:29:21 +02:00
parent 9436c308c3
commit 8225cf6fcd
3 changed files with 235 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
# Relay charter — issue-62-authstorage
## Relay identity
- **Name:** `issue-62-authstorage`
- **Root path:** `relays/issue-62-authstorage/` (in the repo, on branch
`fix/issue-62-authstorage`, worktree `/srv/dev/pi-web-issue-62`)
- **Packet files:** `charter.md`, `status.md`, `log.md` (this directory).
## Background (read once, do not re-derive)
The full technical assessment lives at the worktree root:
`ASSESSMENT-issue-62.md`. Read it once at the start of your leg for the API
migration details; do not re-investigate the SDK from scratch. Short version:
Pi `@earendil-works/pi-coding-agent` 0.80.8 removed the `AuthStorage` export and
replaced the auth/model plumbing with an async `ModelRuntime` + pi-ai
`CredentialStore` model. Pi Web imports `AuthStorage` statically and crashes at
module load with any Pi 0.80.8+. The agreed fix is a **clean migration to the
new `ModelRuntime` API** (no dual-version shim) plus dependency-range
correction, tests, and a changeset. Rationale and the per-file migration shape
are in `ASSESSMENT-issue-62.md` §5.
## Goal / finish line
Pi Web builds, typechecks, lints, and passes its full test suite against Pi
`@earendil-works/pi-coding-agent` **0.80.8+** (target the installed 0.80.8/0.80.10
line), with:
1. No remaining import or use of the removed `AuthStorage` export (and no
reliance on `ModelRegistry.create(authStorage)` / `.inMemory(authStorage)` /
`modelRegistry.authStorage`).
2. Auth, OAuth login, API-key save/logout, provider enumeration, and the
Anthropic subscription warning all working through the new `ModelRuntime` /
`readStoredCredential` / pi-ai `CredentialStore` APIs.
3. `package.json` peerDependencies and devDependencies for the three
`@earendil-works/*` packages corrected so npm cannot resolve an unsupported
release (target range `>=0.80.8 <0.81`; devDeps on a matching `^0.80.8`).
4. A `.changeset/*.md` fragment describing the user-visible fix (no direct
`CHANGELOG.md` edit).
5. `npm run verify` (typecheck + lint + knip + test) passing.
Finish line reached = all of the above true and committed on the branch. **Do
not open a PR** (out of scope for this relay).
## Sizing — one leg
One leg = **one coherent slice** from the plan below that leaves the tree in a
committed, describable state. Prefer the pre-broken-out slices in `status.md`.
A leg does not have to leave `npm run verify` fully green (the migration is
interdependent), but it MUST:
- leave a clear, honest `status.md` describing what compiles/what doesn't yet,
- commit its work with a clear message,
- not expand scope beyond its slice ("just a bit more" is the main failure mode
here — the auth surfaces are interconnected; resist rewriting everything in
one leg).
If a slice turns out bigger than expected, split it and hand off mid-plan with
an updated `status.md` — that is expected and fine.
## Suggested slice breakdown (task selection default)
Follow `status.md`'s named next task. If none is named, pick the lowest-numbered
incomplete slice here:
0. **Bootstrap:** `npm install` in the worktree pinning the three `@earendil-works/*`
packages to 0.80.8+ (e.g. `npm i -D @earendil-works/[email protected]
@earendil-works/[email protected] @earendil-works/[email protected]`), and
correct the peerDependencies range to `>=0.80.8 <0.81`. Confirm the crash
reproduces / the new exports resolve. Commit. (Install in the worktree, NOT
`/tmp``/tmp` has a disk quota problem, see assessment §8.)
1. **`authService.ts` core migration:** move to `ModelRuntime` (async
construction via `ModelRuntime.create({ authPath, modelsPath })`), migrate
saveApiKey/logout/refresh/credential access. Propagate async construction to
`sessiond.ts`. (Session-daemon path — see restart note.)
2. **`authProviderOptions.ts` migration:** rederive login/logout provider
options from `runtime.getProviders()` + `listCredentials()` /
`getProviderAuthStatus()`; update its structural interface + test double.
3. **`oauthLoginFlowService.ts` migration:** reimplement against pi-ai
`AuthInteraction` (`prompt`/`notify`) instead of `OAuthLoginCallbacks`; wire
`runtime.login(providerId, "oauth", interaction)`. (Riskiest slice — verify
prompt/select/device-code/auth_url mapping.)
4. **`piSessionService.ts` migration:** pass `modelRuntime` to
`createAgentSessionServices`; update `PiAgentSession` type; switch
`anthropicSubscriptionWarning` to `readStoredCredential`.
5. **Tests + testSupport:** migrate all test doubles to `InMemoryCredentialStore`
+ `ModelRuntime.create`; get `npm run verify` green. Follow the testing-guide
skill.
6. **Changeset + final verify + cleanup:** add `.changeset/*.md`; run full
`npm run verify`; remove scratch (`ASSESSMENT` stays, `/srv/dev/pi-inspect`
is outside the repo). Confirm goal, hand off to a final confirmation/stop.
Slices may merge or split. 14 depend on 0. Slice 5 finalizes; slice 6 closes.
## Handover
When handing off, `spawn_session` **once** with a prompt whose first line is:
`Relay "issue-62-authstorage" leg <N> begins now.` followed by the standard
Relay handoff body pointing at:
- `relays/issue-62-authstorage/charter.md`
- `relays/issue-62-authstorage/status.md`
Tell the next runner not to read `log.md` end-to-end. Make all work durable
(update `status.md`, append `log.md`, commit) **before** spawning.
## Intervention signal — stop and get the human when:
- The new SDK API does not actually provide an operation the migration needs
(e.g. no viable credential persistence path for API-key save), i.e. the
assessment's assumed mapping is wrong.
- A slice would require changing the charter's goal or the agreed "clean
migration, no shim" decision.
- `npm install` / registry access fails and cannot be resolved in-leg.
- Charter churn: if you find yourself needing to edit this charter to proceed,
stop and involve the human instead.
To raise it: set a clear `## BLOCKED` section at the top of `status.md`, append a
`log.md` entry explaining the blocker and what decision is needed, do **not**
spawn the next leg, and end your run.
## Reading discipline
Read, in order: this `charter.md`, then `status.md`, then `ASSESSMENT-issue-62.md`
(once), then only the specific `src/server/sessions/*` files your slice touches.
Do **not** read `log.md` end-to-end — only targeted entries if `status.md` points
you there. Do not re-extract SDK tarballs unless the assessment is contradicted
by reality.
## Standing constraints (project conventions)
- Session-daemon changes (`sessiond.ts`, session runtime / auth construction
loaded by the daemon) require the human to **manually restart the sessiond
service** to take effect. Call this out in `status.md`/handoff whenever a leg
changes that path so the human knows a restart is pending.
- Follow the skills: `code-quality-architecture` (DI, async boundaries,
testable seams), `testing-guide` (test layers, no over-mocking), and
`changeset-changelog` (changeset not CHANGELOG edit).
- Keep changes scoped to the fix; do not opportunistically refactor unrelated
code.