docs(plan): specify harness declaration + centralized auth/provider registry (#49)
Design only; implementation blocked pending owner review. - agent.json: one harness identifier (pi first), resolved through a versioned adapter/harness manifest; reusable settingsProfile reference - central data-root registry: providers, accounts (metadata + secret credential split), reusable settings profiles, audited runtime selection - per-seat pi auth.json/models.json mechanically generated and atomically activated; no seat/provider registration ceremony - mixed oauth/api-key accounts supported centrally; one active account per provider per pi materialization - host-side centralized OAuth login/refresh; agents never authenticate - local/remote Ollama modeled as endpoint providers, not accounts - target mosaic auth/provider/agent settings CLI; secrets never on argv - migration, fail-closed acceptance suites, and ten explicit review gates CURRENT.md points only to spec review. Suites 24/15/90/14/17 + verify green; unslop clean.
This commit is contained in:
@@ -581,3 +581,36 @@ unified CLI) is owner-gated.
|
|||||||
Suites 24/15/90/14/17 + verify green. Default harness usage is untouched
|
Suites 24/15/90/14/17 + verify green. Default harness usage is untouched
|
||||||
by design; all mosaic-managed credentials live inside the governed data
|
by design; all mosaic-managed credentials live inside the governed data
|
||||||
root.
|
root.
|
||||||
|
|
||||||
|
## Phase 25: harness/provider/auth registry specification (#49)
|
||||||
|
|
||||||
|
- Design-only phase; no implementation authorized. Draft:
|
||||||
|
`docs/plans/2026-09-03_auth-provider-harness-registry.md`.
|
||||||
|
- Agent harness is specified in agent.json as one scalar identifier
|
||||||
|
(`harness: "pi"` initially), resolved through a versioned harness
|
||||||
|
manifest/adapter rather than a permanent hard-coded enum. Existing v1
|
||||||
|
seats migrate with a loud pi default; no CLI harness override in phase 1.
|
||||||
|
- Central registry separates providers, accounts, reusable settings
|
||||||
|
profiles, runtime seat selection, and generated harness files. A seat
|
||||||
|
references one reusable profile; it is not registered with each provider.
|
||||||
|
- Multiple OAuth/API accounts for one provider may be centrally authorized;
|
||||||
|
pi materializes exactly one active account per provider. Runtime selection
|
||||||
|
is audited data-root state; generated auth.json/models.json are disposable
|
||||||
|
per-seat derivatives.
|
||||||
|
- OAuth login/refresh is host-side and centralized; agents never enroll or
|
||||||
|
own refresh tokens. Exact noninteractive pi refresh mechanics remain a
|
||||||
|
required implementation investigation.
|
||||||
|
- Local and remote Ollama are endpoint-provider records materialized into
|
||||||
|
per-seat models.json, independently scoped from authentication accounts.
|
||||||
|
- Target mosaic CLI covers auth account lifecycle, provider lifecycle,
|
||||||
|
refresh/ensure, reusable settings profiles, and seat selection. Secret
|
||||||
|
material is never accepted on argv.
|
||||||
|
- Spec includes registry paths/schemas, naming/perms, fail-closed launch
|
||||||
|
materialization, migration from M19, acceptance suites, and ten explicit
|
||||||
|
owner review gates (including reset/backup semantics and encryption at
|
||||||
|
rest).
|
||||||
|
|
||||||
|
## Result (spec draft)
|
||||||
|
|
||||||
|
Spec is ready for owner/conductor review; CURRENT.md points only to that
|
||||||
|
review. Implementation remains blocked until all ten gates are resolved.
|
||||||
|
|||||||
@@ -15,3 +15,4 @@ are never rewritten or removed; corrections are new entries.
|
|||||||
| 2026-09-03 | owner (decision + live verification) + assistant (conductor) | M18 live verification + follow-up (#46): owner confirmed narrowing/refusal/tool-free live; seatless launch under AGENTS_DIR override discovered and made fail-closed (exit 4); task suite 88 → 90 | scripts/agent.sh, scripts/test-task.sh, docs/TOOLS.md; suites 24/90/14/17 + verify green |
|
| 2026-09-03 | owner (decision + live verification) + assistant (conductor) | M18 live verification + follow-up (#46): owner confirmed narrowing/refusal/tool-free live; seatless launch under AGENTS_DIR override discovered and made fail-closed (exit 4); task suite 88 → 90 | scripts/agent.sh, scripts/test-task.sh, docs/TOOLS.md; suites 24/90/14/17 + verify green |
|
||||||
| 2026-09-03 | assistant (conductor) | M19 harness auth tooling (#47): pi auth investigation (native provider stacking, no native multi-account), scripts/auth.sh status/accounts (never prints credential material), agent.sh --auth per-launch injection via PI_AUTH_FILE, test-auth.sh suite (13 cases incl. secret-never-printed assertions) | scripts/auth.sh, scripts/agent.sh, scripts/test-auth.sh, docs/TOOLS.md, AGENTS.md; suites 24/90/14/17/13 + verify green |
|
| 2026-09-03 | assistant (conductor) | M19 harness auth tooling (#47): pi auth investigation (native provider stacking, no native multi-account), scripts/auth.sh status/accounts (never prints credential material), agent.sh --auth per-launch injection via PI_AUTH_FILE, test-auth.sh suite (13 cases incl. secret-never-printed assertions) | scripts/auth.sh, scripts/agent.sh, scripts/test-auth.sh, docs/TOOLS.md, AGENTS.md; suites 24/90/14/17/13 + verify green |
|
||||||
| 2026-09-03 | owner (direction) + assistant (conductor) | M19 correction (#48): mosaic-managed auth moved from ~/.pi to the data root (auth/<account>.json, 0600 enforced); ~/.pi read-only to the stack as a ROADMAP standing decision; auth.sh config-driven; test-auth 15 cases | scripts/auth.sh, scripts/agent.sh, scripts/test-auth.sh, docs/TOOLS.md, docs/plans/ROADMAP.md, README.md; suites 24/15/90/14/17 + verify green |
|
| 2026-09-03 | owner (direction) + assistant (conductor) | M19 correction (#48): mosaic-managed auth moved from ~/.pi to the data root (auth/<account>.json, 0600 enforced); ~/.pi read-only to the stack as a ROADMAP standing decision; auth.sh config-driven; test-auth 15 cases | scripts/auth.sh, scripts/agent.sh, scripts/test-auth.sh, docs/TOOLS.md, docs/plans/ROADMAP.md, README.md; suites 24/15/90/14/17 + verify green |
|
||||||
|
| 2026-09-03 | owner (requirements) + assistant (conductor/spec author) | Harness/provider/auth registry specification (#49): agent.json harness declaration, centralized providers/accounts/settings profiles, audited runtime selection, per-seat auth/models materialization, centralized OAuth lifecycle, local/remote Ollama, target mosaic CLI | docs/plans/2026-09-03_auth-provider-harness-registry.md; implementation blocked pending ten-gate review; unslop clean |
|
||||||
|
|||||||
@@ -0,0 +1,418 @@
|
|||||||
|
# Harness declaration + centralized auth/provider registry
|
||||||
|
|
||||||
|
Status: **DRAFT FOR OWNER REVIEW** — no implementation is authorized by this
|
||||||
|
file. Issue: #49. Date: 2026-09-03.
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Specify how Mosaic Stack supports multiple harnesses, providers, endpoints,
|
||||||
|
and authentication accounts without modifying a user's default harness
|
||||||
|
configuration or requiring provider registration on every agent seat.
|
||||||
|
|
||||||
|
Pi is the first implementation checkpoint. The registry and seat contracts
|
||||||
|
must remain harness-neutral so future adapters (Claude Code, Codex, OpenCode)
|
||||||
|
materialize their own native files from the same desired state.
|
||||||
|
|
||||||
|
## Non-negotiable decisions already made
|
||||||
|
|
||||||
|
1. Default harness homes (`~/.pi`, and future equivalents) are read-only to
|
||||||
|
Mosaic. The stack never writes there.
|
||||||
|
2. Credentials live only under the configured data root, never in the repo,
|
||||||
|
image, argv, stdout, logs, or generated non-secret manifests.
|
||||||
|
3. Account registration is centralized. A seat never performs OAuth login and
|
||||||
|
does not maintain an independent source credential.
|
||||||
|
4. Seat files are generated artifacts, not user-authored configuration.
|
||||||
|
5. Missing, stale, invalid, insecure, or ambiguous registry/materialized state
|
||||||
|
refuses launch. No fallback to a different account.
|
||||||
|
6. Pi is implemented first; harness-specific behavior stays behind adapters
|
||||||
|
and materializers.
|
||||||
|
|
||||||
|
## Separate concepts (do not conflate)
|
||||||
|
|
||||||
|
| Concept | Example | Authority |
|
||||||
|
|---|---|---|
|
||||||
|
| Harness | `pi`, later `claude-code`, `codex`, `opencode` | `agent.json` + versioned harness manifest |
|
||||||
|
| Provider | `openai-codex`, `anthropic`, `zai`, `ollama-local` | central provider registry |
|
||||||
|
| Account | `openai-codex/homelab-openai` | central account registry |
|
||||||
|
| Endpoint | local/remote Ollama base URL | provider record |
|
||||||
|
| Settings profile | reusable account/provider/model policy | central settings registry |
|
||||||
|
| Seat selection | active choice within a profile's allowed accounts | audited runtime state |
|
||||||
|
| Materialization | harness-native `auth.json` / `models.json` | generated per seat |
|
||||||
|
|
||||||
|
Accounts represent identities. Ollama instances represent endpoints. Harnesses
|
||||||
|
consume generated configuration. Keeping these axes separate prevents account,
|
||||||
|
provider, and model-policy conflicts.
|
||||||
|
|
||||||
|
## Harness declaration: `agent.json`
|
||||||
|
|
||||||
|
A defined seat declares exactly one harness:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"agentVersion": 2,
|
||||||
|
"name": "researcher",
|
||||||
|
"role": "researcher",
|
||||||
|
"harness": "pi",
|
||||||
|
"settingsProfile": "research-default",
|
||||||
|
"capabilities": { "tools": ["read", "bash"] }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `harness` is a scalar identifier, not an array. One process launch runs one
|
||||||
|
harness.
|
||||||
|
- It is not permanently hard-coded to an enum in the agent schema. The value
|
||||||
|
must match a versioned harness manifest/adapter identifier.
|
||||||
|
- Canonical identifiers proposed for review: `pi`, `claude-code`, `codex`,
|
||||||
|
`opencode`. Provider `openai-codex` and harness `codex` remain distinct.
|
||||||
|
- No CLI harness override in phase 1. Harness is part of reviewed seat identity;
|
||||||
|
an override would bypass that declaration.
|
||||||
|
- Migration: existing `agentVersion: 1` seats without `harness` resolve to `pi`
|
||||||
|
with a loud deprecation warning. A later reviewed migration makes version 2
|
||||||
|
and `harness` mandatory.
|
||||||
|
- Plain M13 launches without an agent definition continue to use the system
|
||||||
|
execution adapter; they have no seat enrollment or generated seat auth.
|
||||||
|
|
||||||
|
### Harness manifests
|
||||||
|
|
||||||
|
Harness support is versioned with its adapter, for example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
adapters/pi/harness.json
|
||||||
|
adapters/claude-code/harness.json
|
||||||
|
```
|
||||||
|
|
||||||
|
A manifest declares its identifier, adapter, materializers, native config paths,
|
||||||
|
and supported credential types. Adding a harness requires a reviewed adapter +
|
||||||
|
manifest + suites; it is not a mutable auth-registry operation.
|
||||||
|
|
||||||
|
## Central registry layout
|
||||||
|
|
||||||
|
Fixed below `<dataRoot>`; not configurable independently (config.json remains
|
||||||
|
the sole system config):
|
||||||
|
|
||||||
|
```text
|
||||||
|
<dataRoot>/auth/
|
||||||
|
├── providers/
|
||||||
|
│ ├── openai-codex.json
|
||||||
|
│ ├── anthropic.json
|
||||||
|
│ ├── zai.json
|
||||||
|
│ ├── ollama-local.json
|
||||||
|
│ └── ollama-remote.json
|
||||||
|
├── accounts/
|
||||||
|
│ ├── openai-codex/
|
||||||
|
│ │ ├── homelab-openai/
|
||||||
|
│ │ │ ├── account.json # non-secret metadata, 0600
|
||||||
|
│ │ │ └── credential.json # secret OAuth/API material, 0600
|
||||||
|
│ │ └── personal-openai/
|
||||||
|
│ │ ├── account.json
|
||||||
|
│ │ └── credential.json
|
||||||
|
│ └── zai/
|
||||||
|
│ └── main/
|
||||||
|
│ ├── account.json
|
||||||
|
│ └── credential.json
|
||||||
|
├── settings/
|
||||||
|
│ ├── base.json
|
||||||
|
│ └── research-default.json
|
||||||
|
└── state/
|
||||||
|
├── refresh.json # non-secret status only
|
||||||
|
└── activation-log.jsonl # append-only, no secret material
|
||||||
|
```
|
||||||
|
|
||||||
|
Naming and security:
|
||||||
|
|
||||||
|
- Provider/account/profile IDs match `^[a-z0-9][a-z0-9._-]{0,63}$`.
|
||||||
|
- Display names are metadata; path IDs are explicit or deterministically
|
||||||
|
slugged and confirmed before creation.
|
||||||
|
- Account path must be under its registered provider.
|
||||||
|
- Registry dirs are owner-only; account and credential files are regular,
|
||||||
|
non-symlink, 0600. Loose perms refuse use.
|
||||||
|
- `credential.json` schema depends on type but is never returned by list/status.
|
||||||
|
- Provider removal refuses while accounts/profiles/seats reference it.
|
||||||
|
- Account removal refuses while profiles/selections reference it unless an
|
||||||
|
explicit reviewed migration removes those references first.
|
||||||
|
|
||||||
|
## Registry records
|
||||||
|
|
||||||
|
### Provider
|
||||||
|
|
||||||
|
Native provider example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"providerVersion": 1,
|
||||||
|
"id": "openai-codex",
|
||||||
|
"kind": "native",
|
||||||
|
"harnesses": { "pi": { "providerId": "openai-codex" } },
|
||||||
|
"credentialTypes": ["oauth", "api_key"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Custom endpoint example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"providerVersion": 1,
|
||||||
|
"id": "ollama-local",
|
||||||
|
"kind": "custom-endpoint",
|
||||||
|
"harnesses": {
|
||||||
|
"pi": {
|
||||||
|
"api": "openai-completions",
|
||||||
|
"baseUrl": "http://host.docker.internal:11434/v1",
|
||||||
|
"apiKey": "ollama",
|
||||||
|
"models": ["qwen2.5-coder:7b", "llama3.1:8b"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"credentialTypes": ["none"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`ollama-remote` is a second provider record with its remote base URL, optional
|
||||||
|
credential account, and independently scoped model catalog. Linux compose must
|
||||||
|
provide host-gateway resolution for local Ollama; container `localhost` is not
|
||||||
|
the host.
|
||||||
|
|
||||||
|
### Account metadata
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"accountVersion": 1,
|
||||||
|
"id": "homelab-openai",
|
||||||
|
"name": "Homelab OpenAI",
|
||||||
|
"provider": "openai-codex",
|
||||||
|
"type": "oauth",
|
||||||
|
"createdAt": "<UTC timestamp>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`credential.json` holds the pi-compatible OAuth/API payload centrally. API keys
|
||||||
|
are accepted only from an interactive hidden prompt, stdin, or a validated
|
||||||
|
0600 file — never an argv value.
|
||||||
|
|
||||||
|
### Reusable settings profile
|
||||||
|
|
||||||
|
Profiles remove per-seat/per-provider registration:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"settingsVersion": 1,
|
||||||
|
"id": "research-default",
|
||||||
|
"allowedAccounts": [
|
||||||
|
"openai-codex/homelab-openai",
|
||||||
|
"openai-codex/personal-openai",
|
||||||
|
"zai/main"
|
||||||
|
],
|
||||||
|
"defaultAccounts": {
|
||||||
|
"openai-codex": "openai-codex/homelab-openai",
|
||||||
|
"zai": "zai/main"
|
||||||
|
},
|
||||||
|
"providers": ["ollama-local", "ollama-remote"],
|
||||||
|
"models": {
|
||||||
|
"ollama-local": ["qwen2.5-coder:7b"],
|
||||||
|
"ollama-remote": ["abliterated-model-id"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A seat references one profile. Editing one central profile updates every seat
|
||||||
|
that uses it on the next ensure/launch. The seat is not re-registered with each
|
||||||
|
provider.
|
||||||
|
|
||||||
|
A profile may authorize multiple accounts for the same provider. Pi can place
|
||||||
|
only one entry per provider in one `auth.json`; therefore exactly one account
|
||||||
|
per provider is active for a materialization. Defaults provide the initial
|
||||||
|
selection.
|
||||||
|
|
||||||
|
## Runtime seat selection
|
||||||
|
|
||||||
|
At-will changes are mutable state, not repo edits:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<dataRoot>/agents/<seat>/settings-selection.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"selectionVersion": 1,
|
||||||
|
"profile": "research-default",
|
||||||
|
"accounts": {
|
||||||
|
"openai-codex": "openai-codex/personal-openai"
|
||||||
|
},
|
||||||
|
"updatedAt": "<UTC timestamp>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- Selection can choose only accounts allowed by the seat's referenced profile.
|
||||||
|
- Omitted provider selections use profile defaults.
|
||||||
|
- Changing selection is append-only-audited and triggers regeneration.
|
||||||
|
- No account choice silently falls back to another account.
|
||||||
|
- In-session identity swapping is deferred. Selection normally applies on
|
||||||
|
relaunch/new session; changing identity inside a session risks ambiguous
|
||||||
|
billing, provider state, and audit lineage.
|
||||||
|
|
||||||
|
## Mechanical per-seat materialization
|
||||||
|
|
||||||
|
Generated state:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<dataRoot>/agents/<seat>/generated/pi/
|
||||||
|
├── auth.json # secret, 0600, generated
|
||||||
|
├── models.json # generated custom providers/model scopes
|
||||||
|
└── manifest.json # non-secret inputs/hashes/timestamps; no credential hash
|
||||||
|
```
|
||||||
|
|
||||||
|
Resolution on `agent.sh <seat>`:
|
||||||
|
|
||||||
|
1. Strictly validate agent definition and resolve its harness manifest.
|
||||||
|
2. Resolve role, settings profile, runtime selection, providers, accounts, and
|
||||||
|
model scopes.
|
||||||
|
3. Validate every referenced record, regular-file constraint, ownership, and
|
||||||
|
0600 credential perms.
|
||||||
|
4. Refresh required centralized OAuth records if policy says stale/near expiry;
|
||||||
|
refusal leaves prior generated files untouched.
|
||||||
|
5. Generate beside existing files, validate harness-native output, chmod 0600,
|
||||||
|
then atomically rename into place.
|
||||||
|
6. Compare/write non-secret manifest state and append an activation receipt.
|
||||||
|
7. Mount generated files into the harness's native paths read-only and launch.
|
||||||
|
|
||||||
|
No seat authenticates, edits auth.json, or owns an independent OAuth refresh
|
||||||
|
token. Generated files are disposable derivatives of the registry.
|
||||||
|
|
||||||
|
`mosaic auth ensure [<seat>]` runs the same materializer explicitly. A periodic
|
||||||
|
host service refreshes central OAuth records and rematerializes affected seats;
|
||||||
|
launch-time ensure is the final fail-closed gate. OAuth refresh mechanics must
|
||||||
|
reuse pi's implementation where possible rather than reimplement provider
|
||||||
|
protocols; the exact noninteractive refresh trigger is an implementation
|
||||||
|
investigation and acceptance gate.
|
||||||
|
|
||||||
|
## CLI contract (target `mosaic` surface)
|
||||||
|
|
||||||
|
```text
|
||||||
|
mosaic auth list [--provider <id>] [--json]
|
||||||
|
mosaic auth status [<account-ref>|--seat <seat>] [--json]
|
||||||
|
mosaic auth new
|
||||||
|
mosaic auth new --name "Homelab OpenAI" --provider openai-codex --type oauth
|
||||||
|
mosaic auth rm <provider/account>
|
||||||
|
mosaic auth login <provider/account>
|
||||||
|
mosaic auth logout <provider/account>
|
||||||
|
mosaic auth refresh [<provider/account>|--all]
|
||||||
|
mosaic auth ensure [<seat>|--all]
|
||||||
|
|
||||||
|
mosaic auth provider list [--json]
|
||||||
|
mosaic auth provider status <id> [--json]
|
||||||
|
mosaic auth provider create
|
||||||
|
mosaic auth provider create --id ollama-local --kind custom-endpoint ...
|
||||||
|
mosaic auth provider rm <id>
|
||||||
|
|
||||||
|
mosaic agent settings use <seat> <profile>
|
||||||
|
mosaic agent auth use <seat> <provider/account>
|
||||||
|
mosaic agent auth status <seat>
|
||||||
|
```
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- `new` without sufficient flags launches an interactive wizard.
|
||||||
|
- OAuth `new/login` launches the host-side provider flow once and stores the
|
||||||
|
resulting centralized profile. Agents never run it.
|
||||||
|
- API secret input is hidden prompt/stdin/validated file only.
|
||||||
|
- `rm` reports references and refuses when in use.
|
||||||
|
- Every mutating command writes an append-only secret-free receipt.
|
||||||
|
- `list/status --json` never include credential/token/key fields.
|
||||||
|
- CLI flags name accounts/providers; no secret material is accepted on argv.
|
||||||
|
|
||||||
|
Until M20 provides `mosaic`, `scripts/auth.sh` may prototype the backend, but it
|
||||||
|
must use the same schemas and must not become a competing implementation.
|
||||||
|
|
||||||
|
## Harness-neutral materializers
|
||||||
|
|
||||||
|
Core resolution produces a secret-bearing internal representation in memory:
|
||||||
|
selected providers/accounts/models for one seat. A harness materializer maps it
|
||||||
|
to native files:
|
||||||
|
|
||||||
|
- Pi: `auth.json` + `models.json`.
|
||||||
|
- Claude Code/Codex/OpenCode: future adapter-defined files/env, without changing
|
||||||
|
account/provider/profile schemas.
|
||||||
|
|
||||||
|
The harness manifest declares support. Enrollment or launch refuses if a chosen
|
||||||
|
account/provider cannot materialize for the seat's harness. No best-effort
|
||||||
|
provider dropping.
|
||||||
|
|
||||||
|
## Policy relationships (future phase, not initial implementation)
|
||||||
|
|
||||||
|
Initial authorization is settings-profile enrollment. Later, the existing
|
||||||
|
least-privilege doctrine extends naturally:
|
||||||
|
|
||||||
|
```text
|
||||||
|
role auth ceiling ∩ profile enrollment ∩ mission grant ∩ task grant
|
||||||
|
= effective providers/accounts/models
|
||||||
|
```
|
||||||
|
|
||||||
|
A task may narrow a seat's providers/models, never select an account outside
|
||||||
|
its profile. This is separate from registry and materialization correctness.
|
||||||
|
|
||||||
|
## Migration from M19 prototype
|
||||||
|
|
||||||
|
No named accounts currently exist, so migration is state-free:
|
||||||
|
|
||||||
|
1. Keep `~/.pi/agent/auth.json` as the default harness file, read-only to Mosaic.
|
||||||
|
2. Replace the prototype `<dataRoot>/auth/<account>.json` convention with the
|
||||||
|
registry tree before users create accounts.
|
||||||
|
3. Keep `scripts/auth.sh status/accounts` behavior but drive it from registry
|
||||||
|
schemas.
|
||||||
|
4. Replace `agent.sh --auth <account>` direct-file selection with profile +
|
||||||
|
runtime selection + materialization. A temporary compatibility path may map
|
||||||
|
`--auth provider/account` to a one-launch selection, but must be explicit and
|
||||||
|
audited.
|
||||||
|
5. Add `harness: "pi"` + `settingsProfile` to researcher through an agentVersion
|
||||||
|
migration after review.
|
||||||
|
|
||||||
|
## Required suites / acceptance
|
||||||
|
|
||||||
|
- Registry schemas: unknown keys, path/name mismatch, symlinks, traversal,
|
||||||
|
wrong perms, duplicate IDs, missing provider, unsupported credential type.
|
||||||
|
- Secret non-disclosure: fixture keys/tokens never appear in stdout, stderr,
|
||||||
|
JSON status, manifests, receipts, or git diff.
|
||||||
|
- Referential integrity: provider/account/profile removal refuses while used.
|
||||||
|
- Multiple account types for one provider register successfully.
|
||||||
|
- Profile authorizes multiple same-provider accounts; exactly one active choice
|
||||||
|
materializes for pi.
|
||||||
|
- Changing runtime choice regenerates atomically; failed generation preserves
|
||||||
|
previous files and records refusal.
|
||||||
|
- OAuth central refresh rematerializes affected seats; agents never authenticate.
|
||||||
|
- `harness: pi` resolves; unregistered/unsupported harness refuses.
|
||||||
|
- Pi materialization generates valid auth.json/models.json with scoped providers
|
||||||
|
and models; custom local/remote Ollama entries remain distinct.
|
||||||
|
- Launch refuses missing/stale/invalid materialization; no account fallback.
|
||||||
|
- Existing generic TUI and default-harness use remain untouched.
|
||||||
|
- Full existing suites + verify green.
|
||||||
|
|
||||||
|
## Review gates (must resolve before implementation)
|
||||||
|
|
||||||
|
1. Confirm canonical harness IDs: `pi`, `claude-code`, `codex`, `opencode`.
|
||||||
|
2. Confirm `agentVersion: 2` migration and whether `settingsProfile` becomes
|
||||||
|
mandatory for defined seats.
|
||||||
|
3. Confirm registry path/schema split (`account.json` metadata +
|
||||||
|
`credential.json` secret) versus one encrypted/combined file.
|
||||||
|
4. Decide encryption-at-rest requirement. Filesystem 0600 is specified now;
|
||||||
|
external keyring/envelope encryption would change login/refresh design.
|
||||||
|
5. Confirm selection scope: seat-global only initially, or named launch profiles
|
||||||
|
(e.g. `work`, `personal`) as a first-class layer.
|
||||||
|
6. Confirm whether a seat may switch same-provider account on relaunch only, or
|
||||||
|
whether forked sessions must pin the original account in immutable session
|
||||||
|
metadata.
|
||||||
|
7. Determine pi's supported host-side noninteractive OAuth refresh trigger;
|
||||||
|
implementation must prove refresh without exposing or duplicating tokens.
|
||||||
|
8. Confirm local Ollama container routing (`host-gateway`) and remote Ollama
|
||||||
|
transport/auth requirements.
|
||||||
|
9. Decide whether M20 `packages/mosaic` begins with this auth/provider domain or
|
||||||
|
whether scripts prototype it first.
|
||||||
|
10. Define backup/reset semantics for the central registry. Current reset wipes
|
||||||
|
the data root; OAuth re-login cost may justify a separately protected
|
||||||
|
registry root, but that would require an explicit canon change.
|
||||||
|
|
||||||
|
Implementation is blocked until these gates are reviewed and owner-approved.
|
||||||
@@ -7,7 +7,7 @@ update this file to the next action). No ambiguity, no re-planning.
|
|||||||
|
|
||||||
## Next action
|
## Next action
|
||||||
|
|
||||||
(none queued — M19 completes the agreed ROADMAP sequence M16–M19. M20 — packages/* restructure + unified CLI — is owner-gated per ROADMAP; say "plan M20" to draft its issue, or point at anything else.)
|
Review `docs/plans/2026-09-03_auth-provider-harness-registry.md` against its ten review gates; revise until owner-approved. No implementation starts before approval.
|
||||||
|
|
||||||
## Queue (ordered per docs/plans/ROADMAP.md)
|
## Queue (ordered per docs/plans/ROADMAP.md)
|
||||||
|
|
||||||
@@ -54,3 +54,4 @@ git history + Gitea issues.
|
|||||||
- 2026-09-03 — M18 follow-up: fail-closed seat resolution under MOSAIC_AGENTS_DIR override (#46, owner decision after live verification); task suite 88 → 90; next action M19
|
- 2026-09-03 — M18 follow-up: fail-closed seat resolution under MOSAIC_AGENTS_DIR override (#46, owner decision after live verification); task suite 88 → 90; next action M19
|
||||||
- 2026-09-03 — M19 harness auth tooling (#47; auth.sh status/accounts, agent.sh --auth per-launch injection via PI_AUTH_FILE, test-auth suite 13 cases with secret-never-printed assertions); agreed sequence M16–M19 complete, M20 owner-gated
|
- 2026-09-03 — M19 harness auth tooling (#47; auth.sh status/accounts, agent.sh --auth per-launch injection via PI_AUTH_FILE, test-auth suite 13 cases with secret-never-printed assertions); agreed sequence M16–M19 complete, M20 owner-gated
|
||||||
- 2026-09-03 — M19 correction: auth ownership moved to the data root (#48, owner direction — the stack never writes to default harness config locations; ROADMAP standing decision); auth.sh config-driven, accounts at <dataRoot>/auth, 0600 enforced; test-auth 13 → 15
|
- 2026-09-03 — M19 correction: auth ownership moved to the data root (#48, owner direction — the stack never writes to default harness config locations; ROADMAP standing decision); auth.sh config-driven, accounts at <dataRoot>/auth, 0600 enforced; test-auth 13 → 15
|
||||||
|
- 2026-09-03 — harness/provider/auth registry specification drafted (#49): agent.json harness declaration, central provider/account/settings registries, runtime seat selection, mechanical per-harness materialization, centralized OAuth refresh, Ollama endpoints, CLI contract; implementation blocked pending ten-gate review
|
||||||
|
|||||||
Reference in New Issue
Block a user