Public draftWording is under owner review · content version 0.4 (2026-09-13)

Release history

Changelog

Software version 0.1.0-alpha.4; profile content version 0.4. The machine-readable copy is at /CHANGELOG.md.

# Changelog — joakim.jardenberg.net

Software releases for the public profile site and PPCP/MCP server. Software version and profile content version are distinct: this file tracks the software. The profile content edition is 0.4 (2026-09-13), still under owner review.

The machine-readable copy of this file is served at /CHANGELOG.md.

0.1.0-alpha.4 — 2026-09-13

Error-binding correction found in independent production testing against joakim.jardenberg.net (42/44 grouped checks passed; the two failures were the exact v0.2.1 error payloads for a missing MCP-Protocol-Version header and an unsupported protocol version). No content, key, protocol or design change.

  • signedErrorFrame now signs exactly the v0.2.1 SPEC.md §8 payload { id, error: { code, message } }. Previously any extraData (for example supported / requested for version negotiation) was spread into the signed payload.error, so the signed payload no longer matched the published error test vector.
  • extraData is unchanged on the wire: it still sits in error.data alongside the signed envelope, so MCP version negotiation still sees supported and requested.
  • Setup-page regression: the /mcp "Try it" curl example omitted MCP-Protocol-Version, so the corrected server rejected its own documented example. The example now sends the required MCP-Protocol-Version, Mcp-Method and Mcp-Name headers plus modern _meta, and documents the legacy initialize + 2025-11-25 alternative. A conformance test extracts the exact rendered example from the served HTML and runs it.
  • The example includes a descriptive User-Agent, because the hosting edge in front of this site has been observed to block some default library user-agents (e.g. Python-urllib/3.11) with an edge error before the request reaches the server; named clients are served. Documented as a factual observation; no server-side workaround.
  • ppcp_get_profile description now states "Public draft; owner review pending; AI-assisted editorial wording". Profile 0.4 source unchanged.
  • Regression tests cryptographically verify both failing cases (missing header and unsupported version): the envelope signature is checked against the published JWKS, payload_digest is recomputed from the canonical payload, and the payload's exact key sets are asserted (id, error; code, message), including that negotiation fields are absent from the signed payload.

0.1.0-alpha.3 — 2026-09-13

Transport edge cases found in the alpha.2 review. No content, key or design change.

  • The GET SSE refusal and the DELETE refusal now use the same signed error-frame constructor as every other error; both also carry CORS headers.
  • Origin validation now applies to GET and DELETE as well as POST and OPTIONS, matching the transport's rule for all incoming connections. Origin-less non-browser clients are still accepted.
  • JSON-RPC envelope validation: "jsonrpc": "2.0" is required, and a request id must be a string or a safe integer. Missing/wrong jsonrpc, id: null, and boolean, fractional, array or object ids get a signed -32600 + HTTP 400.
  • Notifications (any method sent without an id) now always return HTTP 202 with no body; a tools/call notification can no longer receive a result.
  • MCP-Protocol-Version is now required as an HTTP header on every non-initialize request that carries an id, including requests with neither the header nor _meta: the oldest advertised revision is 2025-06-18, so an absent header must not silently take an unsupported pre-2025 path. Missing header → signed -32020 HeaderMismatch + HTTP 400. initialize (legacy negotiation) and notifications remain exempt. clientCapabilities must be a JSON object, so arrays are rejected; clientInfo stays optional, as in the spec.
  • Request bodies are decoded as UTF-8 fatally (malformed bytes → signed -32700 + 400) and structural nesting is bounded at depth 32 before any recursive traversal, so deep nesting yields a signed -32600 + 400 rather than an unhandled error.

0.1.0-alpha.2 — 2026-09-13

MCP transport and signing-binding corrections.

  • Implements the 2026-07-28 Streamable HTTP binding: MCP-Protocol-Version must agree with _meta["io.modelcontextprotocol/protocolVersion"], Mcp-Method and (for tools/call / resources/read) Mcp-Name are required and validated against the body, with -32020 HeaderMismatch + HTTP 400 on any mismatch or missing header, including Base64-sentinel decoding.
  • Adds server/discover, resultType: "complete" on every result and io.modelcontextprotocol/serverInfo in result _meta. Unknown methods now return HTTP 404 with -32601; notifications return 202. The legacy initialize path for 2025-11-25 and 2025-06-18 is unchanged.
  • -32022 UnsupportedProtocolVersion lists supported versions for unknown ones.
  • resources/read now signs exactly the result's contents binding, with the exact resource text as the signed text arm.
  • Origin checking uses an exact documented allowlist (no host pattern matching); origin-less clients are still accepted. DELETE returns 405 (stateless).
  • Every JSON-RPC error frame — parse errors, oversized bodies, batch rejection, header mismatches, RPC errors — is now produced by one signed constructor.
  • Request bodies are read with a hard byte bound instead of being buffered first; JSON-RPC batches are rejected; lone UTF-16 surrogates are rejected before anything is canonicalized or signed.

0.1.0-alpha.1 — 2026-09-13

First release of the public profile site.

  • Public, anonymous, account-free reading of the full profile at /, with a sticky contents sidebar, mobile contents drawer, section anchors and in-page search.
  • Exact public Markdown at /profile.md (text/markdown) as the single source for every other representation.
  • PPCP 0.1.0 JSON at /profile.json, validated against the published profile schema, and a signed packaging at /profile.signed.json.
  • Read-only MCP server on POST /mcp (stateless streamable HTTP), with ppcp_get_profile, ppcp_list_sections, ppcp_get_section, ppcp_search, ppcp_get_sources and ppcp_get_version, plus resources/list and resources/read over an exact URI allowlist.
  • Browser setup page on GET /mcp with an endpoint copy button; SSE GET streams are not supported and return 405.
  • org.jardenberg/verifiable-mcp 0.2.1 signing: Ed25519 (EdDSA), RFC 8785 canonicalization, RFC 7638 kid, signed wrapper with iat, payload, payload_digest, content_digest and provenance, signed error frames and signed isError results. Missing key degrades visibly to unsigned.
  • Discovery: /.well-known/mcp.json (with the signing JWKS), /.well-known/ppcp.json, /llms.txt, /robots.txt, /sitemap.xml, /contact.vcf.
  • /about-this-profile, /changelog and /api/health.
  • Schema.org ProfilePage + Person with sameAs to Wikidata and Swedish Wikipedia.