--- id: LSN-0043 ticket: system-os-domain-facades title: SystemOS Domain Facades created: 2026-05-15 tags: [runtime, os, services, api-surface, lifecycle, fs] --- ## Context `SystemOS` became the owner and mediator for core OS services: VM runtime, lifecycle, filesystem, memcard, window management, task/process state and logging. That ownership boundary is correct, but exposing every service field and operation on the root made the OS surface too broad. The solution was not to split ownership back out of `SystemOS`; it was to split the public access surface into short-lived domain views. ## Key Decisions ### Use method-based domain facades **What:** `SystemOS` exposes domain entry points such as: ```rust os.lifecycle() os.sessions() os.vm() os.fs() os.window() ``` Each accessor returns a borrow-friendly facade over `SystemOS` internals. **Why:** Direct fields such as `os.lifecycle.suspend_task(...)` look attractive, but they force ownership shape too early. Method-based views preserve Rust borrowing flexibility while still making the domain boundary explicit. **Trade-offs:** Callers write `os.lifecycle().suspend_task(...)` instead of `os.lifecycle.suspend_task(...)`. The extra call is worth the cleaner ownership model. ### Keep logging on the root **What:** `os.log(...)` remains root-level. **Why:** Logging is cross-cutting, short and used by multiple domains. It is not a broad policy surface in the same way lifecycle, VM, fs or window management are. **Trade-offs:** The root is not empty, but it remains intentionally small. ### Hide migrated internals **What:** Direct access to internal fields such as task/process managers, window manager and VM runtime should disappear once the corresponding facade exists. **Why:** Public internals let callers bypass OS policy. Facades force callers to use the semantic boundary instead of stitching together lower-level services. **Trade-offs:** Tests need domain-level inspection helpers instead of reaching into raw fields. That is better than keeping production internals public for test convenience. ## Patterns and Algorithms Use a short-lived view when an operation needs access to several `SystemOS` fields: ```rust os.lifecycle().crash_task(task_id, Some(&report)); os.vm().tick(vm, signals, hw); os.window().set_focus(window_id); ``` The facade should borrow `SystemOS` or the necessary internals; it must not own duplicated state. If a domain later becomes a true independently owned service, that should be a separate decision. ## Pitfalls - Do not solve a wide root by moving ownership out of `SystemOS` prematurely. - Do not keep raw managers public just because tests need inspection. - Do not make facades long-lived when short-lived method calls avoid borrow pressure. - Do not invent new filesystem behavior while creating an `fs()` facade; expose existing behavior first. ## Takeaways - Ownership boundary and public API shape are separate architectural questions. - `SystemOS` can remain the owner while exposing a narrower domain-oriented API. - Method-based facades are a pragmatic Rust shape for OS domains that coordinate multiple internal services. - A small root API makes OS policy harder to bypass and easier to document.