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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@ All notable changes to this project will be documented in this file. The format

## [Unreleased]

## [1.1.6] - 2026-09-18

### Fixed

- [#451](https://github.com/mohanagy/miftah/issues/451) Stopped a configured identity fingerprint containing a control character from validating, verifying, and then being silently converted into a verification failure. Three layers disagreed about what a storable identity field is: the configuration schema and the probe parser both accepted control characters, while the durable binding store rejected any code point below `0x20` or equal to `0x7f`. A fingerprint that genuinely matched its probe therefore returned `verified` and was then rewritten to `failed` / `IDENTITY_BINDING_UNAVAILABLE`, because the store's record rejection is raised outside `save()`'s own error handling, is caught as a bare failure, and sets a process-sticky unavailable flag that downgraded identity verification for every profile in that process. The single shared predicate is now used by all three layers, so an unstorable fingerprint is refused at configuration time with its exact path and unstorable probe evidence can never reach the store. `doctor` now appends the `IDENTITY_*` code to its explanation, so the cause is recoverable from its output rather than requiring a patched build. Fail-closed behavior on a genuine binding-storage outage is unchanged. Probe tools whose response spans multiple lines remain unusable for identity verification; that limitation is now reported by `miftah validate` instead of surfacing as an unexplained runtime failure.

### Changed

- [#453](https://github.com/mohanagy/miftah/issues/453) Prepared the compatible v1.1.6 patch release delivering the identity-fingerprint fix. No public API, dependency, credential, routing, redaction, or audit behavior changed, and fail-closed behavior on a genuine binding-storage outage is unchanged. Two boundaries tighten deliberately: a configuration carrying a control character in an identity fingerprint is now rejected at validation with its exact path, and probe output containing control characters is no longer accepted as an identity field. Neither could previously produce a durable binding, so no working configuration is invalidated. Publication remains gated on exact `development`-to-`main` promotion and protected OIDC trusted publishing, registry provenance, a fresh install, and package-signature verification; this release does not authorize removal of any legacy behavior.

## [1.1.5] - 2026-09-11

### Changed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Install Miftah, then choose the terminal wizard or the browser Console. Both use
### 1. Install the current release

```bash
npm install -g @lubab/miftah@1.1.5
npm install -g @lubab/miftah@1.1.6
miftah version
```

Expand Down
2 changes: 1 addition & 1 deletion docs/mcp-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This page is the compatibility source of truth for Miftah's downstream MCP server. It records protocol-era behavior separately from generated client-configuration support and from upstream MCP transport support. A generated snippet proves only that Miftah emitted the documented JSON shape; it does not prove that an untested host completed a protocol exchange.

- Miftah baseline: `1.1.5`
- Miftah baseline: `1.1.6`
- Locked MCP TypeScript packages: `@modelcontextprotocol/client`, `core`, `server`, `node`, and `server-legacy` `2.0.0`
- Evidence date: 2026-08-23
- Modern protocol era: `2026-07-28`
Expand Down
2 changes: 1 addition & 1 deletion docs/presets-and-clients.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This is the compatibility source of truth for generated `miftah init` configurat
For downstream protocol eras and real packaged-host evidence, see [MCP protocol and client compatibility](mcp-compatibility.md). The tables below validate generated configuration shapes; they do not by themselves establish a runtime exchange with Claude Desktop, Claude Code, Cursor, or VS Code.

- Catalog version: `3`
- Miftah package version: `1.1.5`
- Miftah package version: `1.1.6`
- Last tested / validation boundary: the catalog builds strict Miftah configuration that `validateConfig` accepts. The docs contract test checks generated configuration only; it does **not** construct a runtime, start, authenticate to, or smoke-test external providers.

Miftah itself requires Node.js `>=20`. That does not establish an upstream server's Node requirement.
Expand Down
4 changes: 2 additions & 2 deletions docs/whats-new-in-0.5.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# What is in Miftah 0.5

Install `@lubab/miftah@1.1.5`, the current stable release, to use the guided setup and account-management capabilities introduced in 0.5 instead of assembling a multi-account configuration by hand:
Install `@lubab/miftah@1.1.6`, the current stable release, to use the guided setup and account-management capabilities introduced in 0.5 instead of assembling a multi-account configuration by hand:

```bash
npm install -g @lubab/miftah@1.1.5
npm install -g @lubab/miftah@1.1.6
miftah version
```

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lubab/miftah",
"version": "1.1.5",
"version": "1.1.6",
"description": "Wrap any MCP. Use the right account without reconnecting.",
"keywords": [
"mcp",
Expand Down
19 changes: 10 additions & 9 deletions tests/release-version.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";

const releaseVersion = "1.1.5";
const releaseVersion = "1.1.6";

function readRepositoryFile(path: string): string {
return readFileSync(new URL(`../${path}`, import.meta.url), "utf8");
Expand All @@ -21,15 +21,15 @@ function releaseNotes(changelog: string, version: string): string {
return changelog.slice(match.index, end < 0 ? undefined : end);
}

describe("v1.1.5 release artifacts", () => {
describe("v1.1.6 release artifacts", () => {
it.each([
{
name: "a non-zero-padded date",
changelog: "## [1.1.5] - 2026-9-11\n\n### Changed\n"
changelog: "## [1.1.6] - 2026-9-18\n\n### Changed\n"
},
{
name: "a heading that does not start its line",
changelog: "Release candidate: ## [1.1.5] - 2026-09-11\n\n### Changed\n"
changelog: "Release candidate: ## [1.1.6] - 2026-09-18\n\n### Changed\n"
}
])("rejects $name", ({ changelog }) => {
expect(() => releaseNotes(changelog, releaseVersion)).toThrow(
Expand Down Expand Up @@ -71,17 +71,18 @@ describe("v1.1.5 release artifacts", () => {
}
});

it("documents the v1.1.5 dependency refresh and its published boundary", () => {
it("documents the v1.1.6 identity fingerprint fix and its published boundary", () => {
const changelog = readRepositoryFile("CHANGELOG.md");
const notes = releaseNotes(changelog, releaseVersion);

expect(notes).toContain("### Fixed");
expect(notes).toContain("### Changed");
for (const issue of [446, 447]) {
for (const issue of [451, 453]) {
expect(notes).toContain(`[#${issue}](https://github.com/mohanagy/miftah/issues/${issue})`);
}
expect(notes).toContain("@hono/node-server");
expect(notes).toContain("dependency refresh rather than a security release");
expect(notes).toContain("This toolchain work is not published");
expect(notes).toContain("control character");
expect(notes).toContain("refused at configuration time with its exact path");
expect(notes).toContain("fail-closed behavior on a genuine binding-storage outage is unchanged");
expect(notes).toContain("protected OIDC trusted publishing");
expect(notes).toContain("registry provenance");
expect(notes).toContain("does not authorize removal of any legacy behavior");
Expand Down