The card tested `p.api_key` on a DTO that has never carried it, so the badge was falsy for every provider and always read "API key missing". The list and the new detail DTO now expose `has_api_key: bool` — the key value itself never reaches the browser, where the edit form used to prefill it in plain text. Since the form can no longer send the stored key back, an empty `api_key` on update means "keep the one on file" instead of erasing it, which is what the field's placeholder already promised.
Skald dev-docs — architectural reference for coding agents. Entry point: ../CLAUDE.md
dev-docs — index
These files hold the design rationale of one subsystem each. They are not loaded into an agent's context automatically: ../CLAUDE.md is, and it names the file to open before touching a given area.
The split criterion is not importance. Everything here is load-bearing — most paragraphs exist to record a trap somebody already fell into ("the obvious alternative is X, and it is wrong because Y"). The criterion is blast radius: a rule a change anywhere can violate stays in CLAUDE.md; the mechanism of one subsystem lives here and is read on entry to that subsystem.
When you change one of these areas, update its file in the same change — same standing rule as docs/ and CHANGELOG.md. A doc written later is written from the diff, which is the version nobody can use.
| File | Read it before touching |
|---|---|
| users-auth-and-boot.md | login, sessions, UserManager, UserContext, per-user DB encryption, what boot unlocks and spawns |
| database.md | any table or accessor under db/, the registry/owner bucket split, memory notes, reports, prompt substitutions |
| filesystem-and-containers.md | container/, the fs-tools, mounts, path routing, skills, the memory signposts, built-in tools |
| projects-and-files.md | projects, shared folders, <file-explorer>, the #files page |
| agent-loop.md | crates/agent-loop/, loop_adapters/, session/handler/, sub-agents, cancellation, restart recovery, the approval gate |
| context-and-compaction.md | compaction, the history window, the cached system-prompt prefix |
| llm-stack.md | LLM clients, providers.yaml, retriability, request logging, token streaming, multimodal attachments |
| mcp-connectors.md | MCP runtimes, connectors, marketplace installs, OAuth, device/QR login |
| plugins.md | plugin visibility, per-user config, HTTP routers, plugin-contributed web pages |
| default-access.md | anything grantable (plugin, connector) and who receives it by default |
| system-agents.md | event triage, the memory lints, the conversation review, their scheduler and settings |
| frontend.md | anything under web/ — components, chat tabs, routing, i18n, theme, the security-group picker |
Two sources of truth sit outside this directory and outrank it:
blueprint/project-family.md— the design document, gitignored and not under version control. Referenced by section number (§0.1, §5.1, §6, §7, §9, §11, §12, §14, §15, §16, §17, §19). Never assume a section says what you remember; open it.../CLAUDE.md— the always-loaded rules: the commit rule, the production/schema constraint, domain neutrality, the event-bus rule, the crate boundaries.