Technical Reference
Security Model
MP-OPT uses separate credentials, trust boundaries, and recovery material so that no single user session, published link, peer copy, or VPS credential grants every capability.
Security trust boundaries
Each boundary uses a different credential and limits what a compromise can reach.
Desktop workstation
Local project database, per-launch backend token, publish credentials in the OS secure store
User device
Passkey private key in the authenticator; session in a protected browser cookie
Public HTTPS boundary
Cloudflare and Caddy
Routing, TLS, headers, and request boundary
FastAPI
Passkeys, sessions, CSRF, roles, reauthentication, limits, and audit
PostgreSQL
Application data, public keys, hashed sessions, and hashed publish secrets
Protected service secrets
Docker secret files on the relevant VPS; node-local HA identities stay local
Operator recovery custody
Only the public age recipient is configured on servers; the private identity remains off-host
Layered security stack
No single control is treated as sufficient; each layer limits or detects a different failure.
What the model protects
| Asset | Protection | Deliberate exposure |
|---|---|---|
| Desktop projects | Local application boundary and per-launch backend token | Only deliberately exported or published data leaves the workstation |
| Private masterplans | Passkey session and backend-enforced event permissions | Authorised event users |
| General Schedules | Separate public representation | Intentionally public fields only |
| Credentials and service secrets | Hashing, OS credential storage, protected secret files, and scoped identities | Only the component that needs the credential |
| Recovery archives | Age encryption, outer hash, receipt, inner manifest, and operator-held private identity | Encrypted packages may be stored externally |
Desktop runtime integrity
- Each packaged application requires an Ed25519-signed manifest covering every regular file in the application, backend and frontend runtime trees.
- Startup stops when the manifest is missing, unsigned, malformed, modified or incomplete, or when an unexpected protected resource is present.
- The shell accepts only explicit HTTP loopback origins, passes one backend URL to the renderer and binds its Content Security Policy to the configured backend origins.
- Shutdown targets only validated child process identifiers registered by that application instance. It does not terminate unrelated Electron applications.
Authentication and sessions
- Web authentication is passkey-only. Private credential keys remain in the platform authenticator or hardware security key.
- Activation, additional-passkey, and recovery ceremonies use short-lived, single-purpose links or exchanges.
- The raw session token is sent only in a Secure, HttpOnly, SameSite=Lax cookie; the server stores its hash.
- Mutating browser requests also require the CSRF cookie and matching request header.
- Sensitive administrative actions require recent passkey reauthentication.
- Session expiry, inactivity, and client binding reduce the value of replayed browser state.
The generated production profile names the cookies __Host-mp_session and __Host-mp_csrf, sets Secure, SameSite=Lax and Path=/ on both, and sets HttpOnly on the session cookie. Their Max-Age follows the server session's absolute expiry. A deployment may configure the names, so its generated privacy notice reports the effective values.
Regular sessions default to 8 hours, privileged sessions default to 1 hour, and all sessions default to a 30-minute inactivity timeout. The configurable bounds are 1–720 hours, 1–24 hours and 5–1,440 minutes respectively. Recent passkey verification defaults to five minutes, configurable from 1–30 minutes. These are software defaults and limits: the controller must confirm the selected values and which privileged operations require step-up verification for each deployment.
Browser-store lifecycle
| Store | Supported content | Removal boundary |
|---|---|---|
| Cookies | Opaque session token and readable CSRF token | Expiry, logout, current-session revocation or browser removal |
| localStorage | Theme, install and notice preferences plus offline opt-in and bounded access metadata; no session token or calendar payload | Preference removal, denied or expired access, applicable logout cleanup or site-data removal |
| sessionStorage and history state | Tab-only dismissals and a transient activation, recovery or shared-route capability after it is removed from the visible URL | Tab or history lifecycle; route capabilities are also cleared after completion or definitive rejection |
| IndexedDB | Explicitly enabled, schema-validated participant-safe offline calendar payload | Expiry, invalid schema, denial, logout, explicit removal or loss of access |
| Cache API | Versioned static application shell and static assets | Service-worker release replacement or site-data removal |
Authenticated API responses are never written to the Cache API. Successful application cleanup covers controlled browser stores only; it does not prove physical deletion from browser or device backups, synchronised profiles or other external copies.
Authorisation
| Role | Scope | Typical authority |
|---|---|---|
| Root administrator | Installation | Security, HA, audit, recovery, and global administration |
| Global administrator | Installation | Cross-event user and event administration without operator key custody |
| Issuer | Assigned event | Invite and manage access for that event |
| Editor | Assigned event | Commit permitted web schedule edits |
| Viewer | Assigned event | Read the authorised schedule |
The interface may hide unavailable actions, but FastAPI enforces every permission independently.
Credential custody
| Credential | Stored where | Not stored where |
|---|---|---|
| Passkey private key | User authenticator | Server and recovery snapshot |
| Desktop publish secret | OS secure credential store; hash on server | Portable project export and server plaintext database |
| Operator evidence private key | Operator workstation OS credential store | Server, SQLite, evidence bundle, Git repository and support output |
| Shared service secrets | Protected Docker secret files | Normal environment-file values or documentation |
| Node HA identity and SSH key | Only its applicable node | Normal peer bundle and recovery snapshot |
| Age recovery private identity | Protected operator custody off-server | Either VPS, peer replication, or snapshot payload |
See Accountability Evidence and Key Custody for proof of possession, rotation, revocation and private-repository anchoring.
Keys are independently generated. Arrows show responsibility, never derivation.
Controller Ed25519
Controller trust and governance statements
Event processor Ed25519
Desktop policy, deletion and local-copy receipts
Root passkey
Human authorisation of privileged Server actions
Instance evidence key
Evidence-chain and final-receipt sealing
Verifiable evidence
Exact statements, signatures, digests and chain links—not proof of physical deletion outside controlled systems
Complete key inventory
| Key | Purpose | Custody and prohibited use |
|---|---|---|
| Root passkey | Authenticates root and authorises exact privileged Server actions | Authenticator only; never signs Desktop receipts or replaces a processor |
| Controller Ed25519 | Establishes controller trust and signs governance statements | Controller custody; not a Server deletion or processor key |
| Event processor Ed25519 | Signs Desktop policy acknowledgements, deletion and local-copy receipts | OS credential store on one event's workstation; never signs Server or governance actions |
| Instance evidence key | Seals evidence-chain records and final deletion receipts | Protected deployment secret; its signature records evidence, not human intent |
| AGE recovery identity | Decrypts exported recovery snapshots | Off-server operator custody; only the public recipient belongs on the VPS |
| Desktop database key | Encrypts protected local Desktop fields | Local OS credential store; not exported as a portable project secret |
| Desktop manifest key | Signs the packaged Desktop runtime file manifest | Release custody; separate from Git tag and processor signing |
| Git tag / Sigstore identities | Authenticate source tags and release artifacts or images | Release workflow custody; never used for runtime data evidence |
| TLS, SSH and HA credentials | Protect transport, peer replication and writer authority | Scoped to nodes/providers; not controller or evidence signatures |
None of these keys is derived from another. Rotation preserves the prior public key and signed history; revocation stops new use but does not erase valid historical signatures.
Evidence sealing and portable verification
The exported ZIP carries the chain, public keys and verification result; private keys never belong in it.
1
Canonical record
Bounded facts and receipt digests
2
Domain signature
Controller, processor, root action or instance seal as applicable
3
Chain link
Previous digest and current record digest
4
Evidence repository
Append-only archive or guarded private mirror
5
Portable ZIP
Records, public keys and verification report
6
Offline verifier
Checks every signature, link and required artifact
Signed release and supply-chain verification
Only the final 3.9.0 candidate may become a supported distribution; the 3.8.2 qualification baseline is never published.
1
Reviewed source
Protected main and Code Owner approval
2
Exact-SHA CI
Tests, docs, audits, licensing and scans
3
Security qualification
Confirmed findings repaired and rescanned
4
Signed tag
Release commit identified by a verified v3.9.0 tag
5
Immutable artifacts
Installer or four Server images, manifest, SBOMs and signatures
6
Operator verification
Checks signature, digest, source identity and supported version
Request and failure hardening
HTTPS, a restrictive Content Security Policy, content-type and body-size validation, rate limits, no-store responses for sensitive data, audit records, and log sanitisation reduce request and disclosure risk. In HA, short write permits are checked before a mutating request and again before ORM commit. If the external writer authority cannot be reached, writes return a service-unavailable response instead of risking split brain.
The maintained attack trees and residual-risk register connect concrete abuse paths to these controls.