Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format

## [Unreleased]

### Added

- [#204](https://github.com/mohanagy/miftah/issues/204) Added guided multi-account Google Search Console onboarding through the CLI and local Console. It creates named profiles with an explicit durable default and separate upstream-owned OAuth state directories per generated configuration file and profile, while continuing to keep browser login, token-cache contents, reauthentication, revocation, and account identity verification outside Miftah.

### Changed

- [#200](https://github.com/mohanagy/miftah/issues/200) Reworked the README into a task-oriented first-use guide with complete Claude Desktop setup, authentication-path selection, generic MCP onboarding, profile-management tools, native versus upstream-owned OAuth, dashboard lifecycle, everyday diagnostics/audit commands, and focused security-control guidance; corrected stale configuration-version guidance to identify v3 as current while preserving an explicit v1/v2 removal window.
Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,15 @@ miftah init gsc \
--client claude-desktop
```

It runs the exact-pinned upstream through `uvx`, applies Miftah's read-only policy, and passes the configured client-secrets path to that upstream. The upstream owns the first-use browser flow and token cache. Miftah never reads, copies, exports, or deletes that cache. See the [Google Search Console provider-adapter pilot](docs/provider-adapters.md#google-search-console-pilot).
It runs the exact-pinned upstream through `uvx`, applies Miftah's read-only policy, and passes the configured client-secrets path to that upstream. The upstream owns the first-use browser flow and token cache. Miftah never reads, copies, exports, or deletes that cache.

To configure one or more named Google accounts behind one connector, use the guided path instead:

```bash
miftah setup gsc --preset google-search-console
```

The wizard asks for one or more named Google accounts, an optional description and client-secrets path for each, then the default profile. Each generated profile gets a different `GSC_CONFIG_DIR`, and Miftah namespaces that directory by the generated configuration file as well as the profile. The exact-pinned upstream therefore keeps its token cache separate even when two configuration files use the same Miftah name. Complete the upstream browser flow separately for every account, then run `miftah validate` and `miftah doctor` against the generated configuration. Separate caches do not verify Google-account identity or property access; confirm those in the upstream before relying on a profile. See the [Google Search Console provider-adapter pilot](docs/provider-adapters.md#google-search-console-pilot).

## Everyday commands

Expand Down
6 changes: 3 additions & 3 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Documented command names, options, JSON success forms, and exit categories are c
| `miftah validate --config <file>` | `--config` | `--config <file>` | Validates the JSON configuration without starting an upstream. Writes a JSON object with `ok`, `name`, and `profiles`. |
| `miftah doctor --config <file>` | `--config` | `--config <file>`, `--json` | Validates configuration and checks upstream readiness. Default output is a human-readable report; `--json` writes only the JSON report. A healthy or degraded report exits `0`; a failed report exits `1`. |
| `miftah schema` | none | none | Writes the Miftah JSON Schema as pretty-printed JSON. |
| `miftah setup [name]` | none | The safe preset options accepted by `init`, except `--interactive` | Opens the guided first-configuration flow. It asks for no secret value, validates the complete candidate, creates the output exclusively with owner-restricted permissions, and can print client JSON for manual review. It never edits a client configuration file. |
| `miftah setup [name]` | none | The safe preset options accepted by `init`, except `--interactive` | Opens the guided first-configuration flow. It asks for no secret value, validates the complete candidate, creates the output exclusively with owner-restricted permissions, and can print client JSON for manual review. For Google Search Console it can collect one or more named accounts and an explicit default. It never edits a client configuration file. |
| `miftah init [name]` | none | `--name <name>`, `--preset <name>`, `--output <file>`, `--interactive`, `--client <claude-desktop\|claude-code\|cursor\|vscode\|all>`, `--credential-env <name>`, `--npm-package <package>`, `--docker-image <image>`, `--url <url>`, `--header-name <name>`, `--header-prefix <prefix>`, `--oauth-client-secrets-file <file>` | Writes a strict catalog configuration with exclusive creation and can print client JSON snippets. The positional `name` and `--name` are alternatives; the default name is `miftah-wrapper`. |
| `miftah migrate-config --config <file>` | `--config` | `--config <file>`, `--write` | Plans a supported configuration-format migration and writes a safe JSON report. It is dry-run by default. `--write` validates the candidate, makes an exact exclusive `<file>.bak`, then uses a same-directory non-overwriting publication for a changed regular non-symlink source; it never resolves secrets or starts an upstream. |
| `miftah connection add --config <file>` | `--config`, `--profile`, `--issuer`, `--client-registration` | `--connection <ref>`, `--upstream <name>`, repeated `--scope <scope>`, `--write` | Plans a v3 OAuth binding by default. `--write` applies the reviewed candidate with a unique recovery backup and configured audit event. It never resolves credentials or starts an upstream. |
Expand Down Expand Up @@ -66,9 +66,9 @@ miftah init "work wrapper" --preset github --output "$HOME/Miftah configs/work w
miftah validate --config "$HOME/Miftah configs/work wrapper.json"
```

`generic-npx` requires `--npm-package` with exact package SemVer; `generic-docker` requires a canonical digest in `--docker-image`; `streamable-http` requires `--url` plus optional credential environment/header metadata; and `google-search-console` requires `--oauth-client-secrets-file` with an absolute path. `--credential-env` is optional where supported. The GSC adapter prints credential/browser/identity ownership without printing that path. See [preset and client compatibility](presets-and-clients.md) for exact inputs, pins, provenance, and client snippets, and [provider adapters](provider-adapters.md) for the upstream-owned OAuth boundary.
`generic-npx` requires `--npm-package` with exact package SemVer; `generic-docker` requires a canonical digest in `--docker-image`; `streamable-http` requires `--url` plus optional credential environment/header metadata; and one-account noninteractive `google-search-console` requires `--oauth-client-secrets-file` with an absolute path. Guided GSC setup can collect one or more named accounts, their client-secrets paths, and an explicit default profile. `--credential-env` is optional where supported. The GSC adapter prints credential/browser/identity ownership without printing a configured path. See [preset and client compatibility](presets-and-clients.md) for exact inputs, pins, provenance, and client snippets, and [provider adapters](provider-adapters.md) for the upstream-owned OAuth boundary.

`--interactive` uses a wizard only when both input and output are TTYs. EOF or Ctrl-C cancels without writing a config. It asks for variable names and safe metadata, never secret values. In noninteractive use, `init` creates only the config unless `--client` is supplied. `--client` prints JSON with absolute Node and compiled Miftah paths; it does not write a host config. For `claude-code` or `all`, it also prints a separate, exact management-tool `permissions.ask` fragment for manual merge into Claude Code settings; it never writes or overwrites those settings. Regenerate the snippets after moving or upgrading Miftah or changing the config path.
`--interactive` uses a wizard only when both input and output are TTYs. EOF or Ctrl-C cancels without writing a config. It asks for variable names and safe metadata, never secret values. For Google Search Console it asks for each account's profile name, optional description, and client-secrets path, then an explicit default profile. In noninteractive use, `init` creates only the config unless `--client` is supplied. `--client` prints JSON with absolute Node and compiled Miftah paths; it does not write a host config. For `claude-code` or `all`, it also prints a separate, exact management-tool `permissions.ask` fragment for manual merge into Claude Code settings; it never writes or overwrites those settings. Regenerate the snippets after moving or upgrading Miftah or changing the config path.

### `migrate-config`

Expand Down
4 changes: 2 additions & 2 deletions docs/console-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ Browser sessions have a 15-minute idle limit and a one-hour absolute limit. Rest

Every request must use the exact listener `Host`. Browser mutations, including bootstrap, must also use the exact listener `Origin`. Normal same-origin navigation and authenticated `GET` and `HEAD` requests may omit `Origin`, because browsers do not consistently attach it to read requests; hostile or duplicate Origin values are still rejected, cross-site cookies remain blocked by `SameSite=Strict`, and every mutation still requires exact Origin plus CSRF. Except for the bootstrap exchange and static application assets, every API endpoint requires the session cookie. JSON request bodies are capped at 64 KiB and must use `Content-Type: application/json`. Headers are capped at 16 KiB. The process admits at most 240 trusted requests per minute and only eight bootstrap attempts per minute; excess requests receive `429` plus `Retry-After`.

`POST /api/v1/sessions`, `POST /api/v1/connections/:ref/connect`, `POST /api/v1/connections/:ref/test`, `POST /api/v1/connections/:ref/reauth`, and `DELETE /api/v1/connections/:ref/credential` must send `Content-Type: application/json` with the JSON body `{}`. `POST /api/v1/connections` instead accepts a strict JSON object with required `profile`, `issuer`, `clientRegistration`, and `scopes` fields plus optional `connectionRef` and `upstream` fields; unknown fields are rejected. The first-run endpoint accepts only non-secret configuration name, profile, description, exact resource/issuer, client-registration mode, and scopes; token, password, cookie, secret, callback, and arbitrary extra fields are rejected.
`POST /api/v1/sessions`, `POST /api/v1/connections/:ref/connect`, `POST /api/v1/connections/:ref/test`, `POST /api/v1/connections/:ref/reauth`, and `DELETE /api/v1/connections/:ref/credential` must send `Content-Type: application/json` with the JSON body `{}`. `POST /api/v1/connections` instead accepts a strict JSON object with required `profile`, `issuer`, `clientRegistration`, and `scopes` fields plus optional `connectionRef` and `upstream` fields; unknown fields are rejected. Native-OAuth first run accepts only non-secret configuration name, profile, description, exact resource/issuer, client-registration mode, and scopes. Reviewed-preset first run accepts only safe catalog metadata; for Google Search Console that can include strict named account objects containing a profile name, optional description, and client-secrets path, plus an explicit default when there is more than one account. Token, password, cookie, raw secret contents, callback, and arbitrary extra fields are rejected.

| Method and path | Purpose |
| --- | --- |
| `POST /api/v1/sessions` | Exchange the one-use bootstrap code for one browser session. |
| `POST /api/v1/onboarding/preset` | Exclusively create the first validated configuration from a reviewed preset and safe connector metadata. Requires CSRF; raw credential values are rejected. |
| `POST /api/v1/onboarding/preset` | Exclusively create the first validated configuration from a reviewed preset and safe connector metadata. Requires CSRF; GSC accepts only structured account names/descriptions/client-secrets paths and rejects raw credential values. |
| `POST /api/v1/onboarding/native-oauth` | Exclusively create the first validated v3 native-OAuth profile, upstream, and connection. Requires CSRF and refuses an existing file. |
| `GET /api/v1/health` | Return safe config identity, Console audit health, and restart-required guidance. |
| `GET /api/v1/config` | Return allowlisted configuration metadata only. |
Expand Down
4 changes: 2 additions & 2 deletions docs/oauth-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The [OAuth and local Console design delta](oauth-console-threat-model.md) record
| Support class | Transport and current ownership | Operator fallback |
| --- | --- | --- |
| Standards-compatible remote HTTP MCP OAuth | Enabled for an exact HTTPS `streamable-http` connection whose protected-resource and authorization-server metadata satisfy Miftah's discovery checks. Miftah owns browser authorization, the bounded loopback callback, exchange, vault storage, refresh, and bearer injection. | If the server does not advertise the required standards, use its documented API-key, static-header, or provider-owned flow. |
| Provider-adapter-backed local or non-standard OAuth | The built-in [Google Search Console pilot](provider-adapters.md#google-search-console-pilot) launches an exact-pinned local upstream and publishes its ownership contract. OAuth, browser handoff, token cache, reauthentication, and revocation remain upstream/manual-owned; this is not native Miftah OAuth. | Complete the upstream's documented login and configuration. The typed adapter supplies bounded launch and safe health metadata without cache access. |
| Provider-adapter-backed local or non-standard OAuth | The built-in [Google Search Console pilot](provider-adapters.md#google-search-console-pilot) launches an exact-pinned local upstream and publishes its ownership contract. For generated GSC profiles, Miftah supplies a distinct `GSC_CONFIG_DIR` per generated configuration file and profile; OAuth, browser handoff, the cache created there, reauthentication, and revocation remain upstream/manual-owned. This is not native Miftah OAuth. | Complete the upstream's documented login and configuration. The typed adapter supplies bounded launch and safe health metadata without cache access. |
| Upstream-owned or manual credentials | `stdio`, legacy `sse`, and remote Streamable HTTP headers remain supported. The upstream/provider owns login, callback, token cache, refresh, reauth, and revoke. | Complete the provider-owned login, supply its documented credential path, environment value, or static secret reference, then run `miftah validate` and `miftah doctor`. |
| Unsupported authentication patterns | Provider passwords, browser cookies, and arbitrary third-party token caches are not a supported Miftah-managed OAuth mechanism. Miftah does not own, parse, scrape, import, replay, or lifecycle-manage provider passwords, browser cookies, or arbitrary third-party token caches as OAuth artifacts. | Use a provider-supported mechanism, or leave that upstream unconfigured when its only path depends on opaque private state. |

Expand Down Expand Up @@ -103,7 +103,7 @@ The exact OAuth-bound Streamable HTTP transport receives the profile-bound OAuth

## Local and provider-owned OAuth

For Google Search Console-style local OAuth, the [Google Search Console pilot](provider-adapters.md#google-search-console-pilot) generates an exact-pinned local `uvx mcp-search-console@0.3.2` process configured with a provider client-secrets file. Complete the upstream's browser login on first use and let that upstream create and maintain its own local credential cache. **Miftah must not scrape, copy, or manage that upstream token cache.**
For Google Search Console-style local OAuth, the [Google Search Console pilot](provider-adapters.md#google-search-console-pilot) generates an exact-pinned local `uvx mcp-search-console@0.3.2` process configured with a provider client-secrets file. Each generated configuration file and profile gets a separate `GSC_CONFIG_DIR`; complete the upstream's browser login on first use and let that upstream create and maintain its own credential cache in that directory. **Miftah must not scrape, copy, or manage that upstream token cache.** Separate cache paths do not verify the authorized Google account or property.

The same rule applies when Sentry or another upstream MCP server owns consent, redirects, or cached tokens. Miftah may pass an explicit configured path or secret reference to the child and redact resolved values. It does not reinterpret an opaque provider cache as a native Miftah OAuth connection.

Expand Down
Loading