# Changelog All notable changes to Switchboard Core are documented here. ## v0.6.7 — Native mTLS End-to-end mutual TLS without a reverse proxy. Targets systemd+podman deployments where the Go binary terminates TLS itself. ### Added - **`TLS_MODE` config**: Three values — `none` (default, plain HTTP), `server` (TLS, no client cert), `mtls` (mutual TLS, client cert required). Independent of `AUTH_MODE`. Combinations: `server`+`builtin` for HTTPS with password auth, `mtls`+`mtls` for full mTLS identity, `none`+`mtls` for proxy-terminated (existing behavior). - **TLS server mode**: Binary calls `ListenAndServeTLS` directly when `TLS_MODE` is `server` or `mtls`. TLS 1.3 minimum, no cipher suite configuration. Config: `TLS_CERT`, `TLS_KEY`, `TLS_CA` path env vars. - **`MTLSNativeProvider`**: New auth provider that reads `r.TLS.PeerCertificates[0]` directly — no header trust. `Subject.CommonName` becomes username, `sha256(cert.Raw)` becomes `external_id`. Auto-provisions users identically to the proxy provider. Selected when `AUTH_MODE=mtls` and `TLS_MODE=mtls`. - **Shared mTLS helpers**: `ParseDN()`, `FingerprintCert()`, and `resolveOrProvision()` extracted to `mtls_helpers.go`. Both proxy and native providers consume the same user resolution logic. - **Peer TLS config**: `BuildPeerTLSConfig()` constructs a `*tls.Config` for outbound node-to-node connections (forward-looking — cluster registry is currently DB-backed with no HTTP peer calls). - **`switchboard-ca.sh`**: Shell wrapper around openssl for cert provisioning. Three commands: `init` (CA keypair), `issue-node` (365d, ServerAuth + ClientAuth EKU), `issue-user` (90d, ClientAuth only). All ECDSA P-256, PEM output. - **12 new tests**: `FingerprintCert` determinism, native provider unit tests (nil TLS, empty certs, no CN, email extraction), TLS integration tests (no cert rejected, wrong CA rejected, expired cert rejected, valid cert accepted, peer certificate visibility). ### Changed - **`MTLSProvider` → `MTLSProxyProvider`**: Renamed for clarity. Config type `MTLSConfig` → `MTLSProxyConfig`. Constructor `NewMTLSProvider` → `NewMTLSProxyProvider`. File `mtls.go` → `mtls_proxy.go`. ## v0.6.6 — Final Hardening Final pass before public release. Security, correctness, and developer experience. No new features — only fixes, validation, and cleanup. ### Added - **`ValidateManifest()` gate**: Centralized manifest validation function (`package_validate.go`) called at both upload-install and bundled-install time. Catches malformed manifests early with clear error messages. 12 unit tests covering all type constraints and edge cases. - **Extension dependency auto-activation**: Installing a package whose `dependencies` list an uninstalled library will auto-install that library from the bundled packages directory. If the dependency is not bundled, the error message lists exactly what's missing. - **`OptionalAuth` middleware**: New page middleware for workflow visitor routes. Authenticates if a token is present, allows anonymous pass-through otherwise. Replaces the stale `AuthOrRedirect` TODO for Session routes. - **Package signing schema reservation**: `signature` field accepted in manifest (no-op). `PACKAGE_VERIFY_SIGNATURES` env var logs warnings for unsigned packages when enabled. No cryptographic verification yet — schema slot reserved to prevent a breaking change later. - **ICD/SDK runner v0.6.x coverage**: Smoke tier adds metrics, cluster, backups, docs, and OpenAPI JSON endpoints. SDK admin domain adds metrics, cluster, and backups dual-path tests. ### Fixed - **OIDC nonce validation**: ID token nonce claim is now validated against the stored authorization request nonce. Previously the nonce was generated and stored but never checked on callback — a token replay/substitution vulnerability. ### Changed - **Schema migration stub**: `RunSchemaMigrations()` no longer pretends to work. Replaced with a log-only function documenting that only additive schema changes are supported. Downgrade rejection preserved. - **Session middleware TODO resolved**: `main.go` Session slot now uses `OptionalAuth` instead of `AuthOrRedirect`. OIDC nonce TODO and migration stub TODO also resolved. ## v0.6.5 — Renderer Pipeline + Docs Rewrite Lifts block rendering to a kernel SDK primitive so all surfaces share one markdown pipeline. Rewrites docs for external audience. Adds CONTRIBUTING guide and extension tutorial. ### Added - **`sw.renderers` SDK module**: Kernel-level renderer registry. Extensions register block renderers (fenced code blocks) and post renderers (DOM post-processing) once; all surfaces consume via `sw.markdown`. - **`sw.markdown` SDK module**: Unified markdown rendering via `marked` v16 (vendored). Lazy-loads `marked` + DOMPurify. Custom code hook delegates fenced blocks to `sw.renderers`. Wikilink tokenizer (`[[Page Name]]`) built in for all surfaces. - **Browser extension script loader**: Server injects `