Architektur + Sicherheit

Spezifikation

Quelldokument: documentation/architecture/mcp-platform-v1.md im Source-Tree. Verbindlichkeit nach RFC 2119 (MUST / SHOULD / MAY). Version: v1. Umfang: ~2300 LOC.

Die Implementierung referenziert die Spec-Abschnitte (z.B. §7.4.2 fuer das Caretaker-Modell). Aenderungen an der Spec durchlaufen denselben Review-Prozess wie Code.


Protokoll

FeldWert
ProtokollModel Context Protocol (MCP)
Version2025-03-26
TransportHTTP + Server-Sent Events
Wire-FormatJSON-RPC 2.0
Lifecycleinitializetools/listtools/call
Capabilitiestools.listChanged: true
notifications/tools/list_changednicht implementiert (Backlog)
Konformitaets-Testmcp-inspector

Transport-Sicherheit

TLS

FeldWert
StackQt6 QSslSocket + System-OpenSSL
VersionenTLS 1.3, 1.2
Server-CertRSA-4096, SAN-bound, 10 Jahre
Cert-Regenerierungbei Bind-Adress-Aenderung
SAN-ValidierungRFC 6125
Cipher-SuitesOpenSSL-Defaults (Distribution-gehaertet)
Selbst-implementierte Kryptokeine

mTLS (optional)

Aktiv sobald ~/.config/ForgeIEC/mcp/trust/*.pem mind. ein CA-Cert enthaelt.

FeldWert
peerVerifyModeQueryPeer
Fallback ohne Client-CertBearer-Auth
Chain-ValidationQt-SSL-Stack
Subject-Pruefunggegen peers.toml (eigene Implementierung)

Federation-Roster

Datei-Layout

# peers.toml
[meta]
sequence_number = 17
signed_ts = "2026-05-12T18:00:00Z"
signed_by = "ForgeIEC-Team-CA"
ca_fingerprint_sha256 = "ba:fc:ef:..."
signature_b64 = "..."

[[peer]]
name = "alice@team"
fingerprint_sha256 = "ab:cd:..."
role = "author"
endpoint = "https://alice-ws.factory:7531"

Analog revoked.toml fuer Revocation-Liste.

Signatur

FeldWert
AlgorithmusEd25519 (bevorzugt) oder RSA-PSS-SHA256
Implementierungopenssl pkeyutl shell-out
Signatur-PayloadDatei ohne signature_b64-Zeile (line-orientiert)
Replay-Schutzmonotone sequence_number, persistiert in QSettings
Verteilungs-Kanalbeliebig (Git, S3, HTTP, USB)

Code-Pfad

FMcpPeerRoster::verifySignature (Editor), FMcpCaretaker::signCsr fuer Signing-Inverse. Reload via QFileSystemWatcher mit 200 ms Debounce.


Confirmation State Machine

Quelldatei: FConfirmationStateMachine. Spec: §9.5.

Ablauf

sequenceDiagram
    participant Client as LLM-Client
    participant Server as MCP-Server
    participant FSM as State Machine
    participant Op as Operator

    Client->>Server: tools/call (project.write.add_variable)
    Server->>FSM: suspend(question, options, context)
    FSM-->>Server: pending_id
    Server-->>Client: FORGE_ERR_CONFIRMATION_REQUIRED + pending_id
    Note over Client,Op: Frage erscheint im Chat
    Op->>Client: "yes"
    Client->>Server: tools/call (editor.confirm, id, "yes")
    Server->>FSM: resume(id, "yes")
    FSM->>Server: original handler mit force=true
    Server-->>Client: Result des urspruenglichen Tools

Eigenschaften

FeldWert
Pending-IDUUIDv4
Timeout5 min Default, pro-Tool override
Bypassnur via force=true, gesetzt durch State Machine selbst
Auditappend-only JSONL in ~/.config/ForgeIEC/mcp_audit.log
Read-APIeditor.pending_confirmations

Write-Zugriff: drei Pruefungen

Pruefung 1 — Build-Time

option(MCP_OVERRIDE_SECURITIES "Unlock MCP write tools" OFF)

Default OFF. Preprocessor-konditional — disabled Code-Pfade sind im Default-Binary nicht enthalten. Kein Runtime-Switch.

Pruefung 2 — State Machine

Jedes schreibende Tool durch §9.5 (siehe oben).

Pruefung 3 — Sichtbarkeit

KanalInhalt
Chat-Verlaufjeder Tool-Call sichtbar
~/.config/ForgeIEC/mcp_audit.logJSONL, append-only, Timestamp + Tool + Args + Choice
initialize.instructionsSecurity-Override-Banner wenn Build-Time-Flag aktiv
warnings[] in ResponsesOverride-Banner wiederholt

Force-Pfad

Force-Setzungen (Wert-Pinning unabhaengig vom Programm) sind nicht ueber MCP zugaenglich — kein force.*-Tool weder im Default- noch im Override-Build.

Defense-Layer

LayerMechanismus
1 — Codegen-TOML-DFORCING_ENABLED cmake-Option der PLC-Runtime
2 — anvild RPCForceVariable-Endpoint prueft PLC-Build-Mode
3 — Editor-UIF-Checkbox greyout wenn PLC-Build kein Force
4 — MCPkein Tool registriert

MCP-Read-Side: monitor.snapshot liefert forced=true|false pro Variable (Anvil-gRPC is_forced-Feld).


Human-Identification

Quellklasse: FMcpFingerprintArt. Spec: §7.6.

Memorable-ID

FeldWert
EingangSHA-256-Fingerprint (32 Byte)
Bit-Sliceerste 44 Bit, geslicet in 4 × 11 Bit
WordlistBIP-39 English (2048 Eintraege)
Formatword-word-word-word
Bit-Flip-Sensitivitaet (erste 44 Bit)4/4 Wortwechsel

Randomart

FeldWert
AlgorithmusOpenSSH drunken-bishop (ssh-keygen -lv -E sha256)
Grid17 × 9
Augmentation-String" .o+=*BOX@%&#/^SE"
MarkerS = Start, E = Bishop-Endposition

Surfaced in

EndpunktInhalt
server_info.trust_store_cas[]pro Trust-Store-CA
team.list_peerspro Peer
team.request_certfuer frisch ausgestellten Cert

Caretaker-Modell

Quellklasse: FMcpCaretaker. Spec: §7.4.

Datei-Layout

~/.config/ForgeIEC/mcp/ca-team/
  ca.key   RSA-4096, 600-permissions
  ca.crt   X.509, CA:TRUE, 10 Jahre
                keyCertSign + cRLSign + digitalSignature

Aktivierung

VoraussetzungForm
Build-TimeMCP_OVERRIDE_SECURITIES=ON
Runtime-FlagQSettings mcp/caretaker_enabled
Modal-Bestaetigungliteral “I accept Team-CA responsibility”
Datei-Existenzca.key + ca.crt parse-valid

FMcpCaretaker::isCaretaker() returnt true nur wenn alle 4 erfuellt.

Operationen

ToolStatus
team.list_peers (Member + Caretaker)done
team.request_cert (Caretaker)done
team.revoke_peer (Caretaker)Stub (revoked.toml-Mutation Backlog)
team.rotate_cert (Member)Backlog
team.export_setup (Caretaker)Backlog

Alle Mutationen via State Machine.

Multi-Caretaker (HA)

Mehrere Caretakers moeglich. Konflikt-Resolution per monotoner sequence_number im signierten Roster.


Audit + Reproducibility

AspektStand
Audit-Logappend-only JSONL, kein delete-Pfad
Audit-Feldertimestamp, tool, args, choice, called_by
Codegen-Determinismusbyte-identisches POUS.c pro .forge
Test-Coverage117+ Tests, IEC-Sprache + 132 Lib-Bausteine + Multi-Task + Persist + Force
Jitter-Testphysikalische Messung gegen Baseline

Implementierungs-Sprachen

Editor

C++17 + Qt6. RAII via QObject-Parent-Chain. Implicit-shared QObjects fuer Cross-Thread-Snapshots. Keine globalen mutablen Zustaende.

Module der MCP-Schicht:

KlasseDatei
FMcpServereditor/src/runtime/FMcpServer.cpp
FMcpCertManagereditor/src/runtime/FMcpCertManager.cpp
FMcpTrustStoreeditor/src/runtime/FMcpTrustStore.cpp
FMcpPeerRostereditor/src/runtime/FMcpPeerRoster.cpp
FMcpCaretakereditor/src/runtime/FMcpCaretaker.cpp
FMcpFingerprintArteditor/src/runtime/FMcpFingerprintArt.cpp
FConfirmationStateMachineeditor/src/runtime/FConfirmationStateMachine.cpp
FMcpAuditLogeditor/src/runtime/FMcpAuditLog.cpp

Runtime-Server

anvild: Rust + Tokio + tonic. Memory-sicher per Borrow-Checker. gRPC-Proto: anvil-server/proto/plc_service.proto.

IPC

iceoryx2 (Rust + C-FFI). ABI-Probe gegen Type-Hash-Drift: anvil-shared@50cb29f. Drei Defense-Layer gegen mismatched Versionen.


Standards

StandardVerwendung
IEC 61131-3Programmiersprache + Compile-Path (matiec)
PLCopen XMLProjekt-Dateiformat
RFC 6125TLS-Server-Cert SAN-Validation
RFC 8032 (Ed25519)Roster-Signatur (bevorzugt)
RFC 8017 (RSA-PSS)Roster-Signatur (HW-Token-Interop)
BIP-39 (English)Memorable-ID Wordlist
SSH ssh-keygenRandomart-Algorithmus
MCP 2025-03-26Protokoll
JSON-RPC 2.0Wire-Format
RFC 2119Spec-Verbindlichkeits-Sprache
TOML 1.0Konfiguration

Offene Punkte (Stand 2026-05-12)

ItemStatus
team.revoke_peer Voll-ImplementierungStub
team.rotate_certBacklog
team.export_setupBacklog
OCSP / CRL handlingnicht implementiert
Memorable-ID-Typing-Confirmation (§7.4.2)derzeit yes/cancel
notifications/tools/list_changed SSEnicht emittiert
Hardware-Token (PKCS#11 / FIDO2) fuer CA-KeyRoadmap
force.* Tool-FamiliePhase-3 Backlog
Bulk-Mode (MCP-10)Backlog
Caretaker-Toggle-UI in PreferencesBacklog

Vollstaendige Liste: project_open_backlog.md (intern).


Lizenz

AGPL-3.0-or-later fuer alle Subprojekte. Source einsehbar. Reproducible-Build via Debian CPack + signed APT-Repository.


Kontakt

Security-Reports + Audit-Anfragen: blacksmith@forgeiec.io — verantwortliche Offenlegung bevorzugt.


Weiter