# Architecture Demarkus is a Go monorepo with four modules connected by local `replace` directives. ## Module Boundaries - **protocol/** — Wire format types, parsing, serialization. No network code. The foundation everything else depends on. - **server/** — QUIC server. Accepts Mark Protocol requests over QUIC streams, routes to handlers. Depends on protocol. - **client/** — CLI, TUI (Bubble Tea), and MCP server. All three share the same protocol client. Depends on protocol. - **tools/** — Dev utilities like `demarkus-token` for generating auth tokens. ## Key Design Decisions ### Stream Abstraction `handler.Stream` is just `io.ReadWriteCloser`. This means handler tests don't need QUIC — they use mock streams (bytes.Buffer or similar). The entire handler layer is testable without network setup. ### Frontmatter as map[string]string Parsed frontmatter uses `map[string]string` rather than typed structs. This avoids YAML auto-typing issues (e.g., `yes` becoming `true`) and keeps the parsing layer simple. Type conversion happens at the handler level where context is known. ### Versioned Store with Symlinks Documents are stored as versioned files with symlinks pointing to current: ``` content-root/ doc.md -> versions/doc.md.v3 versions/ doc.md.v1 doc.md.v2 doc.md.v3 ``` Each version is immutable once written. SHA-256 hash chain links versions together for integrity verification. ### Capability-Based Auth Tokens grant capabilities, not identities. Server stores SHA-256 hashes in TOML, never raw tokens. Each token is scoped to path globs and specific operations. The server doesn't know or care who you are — only what you're allowed to do. ### Path Traversal Defense `filepath.Clean` + `..` check. Returns `not-found` (not `forbidden`) to avoid leaking information about server structure. ### Status as Text Human-readable status strings (`ok`, `not-found`, `conflict`) instead of numeric codes. Fits the markdown-native philosophy — everything should be readable. ## Wire Format **Request**: `VERB /path\n` followed by optional YAML frontmatter and body. **Response**: YAML frontmatter (always includes status) + markdown body. Protocol constants: port `6309`, ALPN `"mark"`, scheme `mark://`. ## What I've Internalized The architecture rewards simplicity. When I'm tempted to add abstraction, the right move is usually to keep the function short and the flow obvious. Fritz and I have a shared instinct here: if a solution feels clever, it's probably wrong. The best code in this project reads like prose.