354 lines
11 KiB
Markdown
354 lines
11 KiB
Markdown
---
|
|
id: AGD-0034
|
|
ticket: system-os-domain-facades
|
|
title: Agenda - SystemOS Domain Facades
|
|
status: accepted
|
|
created: 2026-05-15
|
|
resolved: 2026-05-15
|
|
decision: DEC-0026
|
|
tags: [runtime, os, services, api-surface, lifecycle, fs]
|
|
---
|
|
|
|
# Agenda - SystemOS Domain Facades
|
|
|
|
## Contexto
|
|
|
|
Depois de `DEC-0024` e `DEC-0025`, `SystemOS` passou a concentrar ownership e
|
|
coordenação de vários domínios do Prometeu OS:
|
|
|
|
```text
|
|
SystemOS
|
|
vm_runtime
|
|
process_manager
|
|
task_manager
|
|
window_manager
|
|
log_service
|
|
fs / fs_state / open_files / next_handle
|
|
memcard
|
|
lifecycle methods
|
|
VM initialize/tick helpers
|
|
```
|
|
|
|
Essa concentração é correta do ponto de vista de ownership: o OS deve ser dono
|
|
ou mediador dos serviços do console. O problema agora é a superfície pública do
|
|
root. Se tudo fica como `os.bla()`, `os.campo.bla()` ou campos públicos soltos,
|
|
o `SystemOS` vira um objeto largo demais e deixa de comunicar domínio.
|
|
|
|
A intenção proposta é separar a superfície em compartimentos:
|
|
|
|
```text
|
|
os.lifecycle().suspend_task(...)
|
|
os.lifecycle().resume_task(...)
|
|
os.lifecycle().crash_task(...)
|
|
|
|
os.sessions().create_vm_game_task(...)
|
|
os.sessions().create_vm_shell_task(...)
|
|
os.sessions().create_native_shell_task(...)
|
|
|
|
os.vm().initialize(...)
|
|
os.vm().tick(...)
|
|
|
|
os.fs().mount(...)
|
|
os.fs().open(...)
|
|
os.fs().read(...)
|
|
os.fs().write(...)
|
|
os.fs().close(...)
|
|
|
|
os.window().add_window(...)
|
|
os.window().set_focus(...)
|
|
os.window().focused_window(...)
|
|
os.window().close_window(...)
|
|
```
|
|
|
|
Logging pode continuar na raiz como operação transversal:
|
|
|
|
```text
|
|
os.log(...)
|
|
```
|
|
|
|
## Problema
|
|
|
|
O `SystemOS` está crescendo wild na raiz. Isso cria alguns riscos:
|
|
|
|
- novos domínios tendem a adicionar mais métodos diretamente em `SystemOS`;
|
|
- lifecycle, filesystem, window, VM runtime e memcard competem pela mesma
|
|
superfície;
|
|
- testes e firmware continuam alcançando managers internos diretamente;
|
|
- fica difícil distinguir API semântica de OS de detalhe interno de serviço;
|
|
- a raiz pública pode virar uma coleção de campos públicos em vez de uma
|
|
interface de sistema.
|
|
|
|
O ponto importante: não queremos desfazer o ownership do `SystemOS`. Queremos
|
|
compartimentalizar o acesso.
|
|
|
|
## Pontos Criticos
|
|
|
|
- `SystemOS` deve continuar sendo o boundary de ownership e coordenação.
|
|
- Facades não devem virar owners independentes que duplicam estado.
|
|
- A raiz do OS deve ficar pequena e expressiva.
|
|
- Lifecycle deve continuar coordenando `TaskState` e `ProcessState` junto.
|
|
- Filesystem tem estado composto (`VirtualFS`, `FsState`, `open_files`,
|
|
`next_handle`) e por isso se beneficia de uma facade própria.
|
|
- Window management já é serviço do OS, mas `PrometeuHub` e firmware ainda
|
|
acessam `os.window_manager` diretamente.
|
|
- VM runtime talvez também precise de facade ou área própria, mas isso pode ser
|
|
uma etapa posterior para não misturar com lifecycle/fs.
|
|
- O formato da facade precisa respeitar borrow rules em Rust; campos públicos
|
|
simples podem não ser viáveis quando uma operação precisa de múltiplos campos
|
|
internos do `SystemOS`.
|
|
|
|
## Opcoes
|
|
|
|
### Opcao A - Manter tudo na raiz do SystemOS
|
|
|
|
**Abordagem:**
|
|
Continuar adicionando métodos e campos diretamente em `SystemOS`.
|
|
|
|
**Vantagens:**
|
|
- menor mudança imediata;
|
|
- callsites simples;
|
|
- menos tipos auxiliares;
|
|
- evita atrito com borrow checker.
|
|
|
|
**Custos / Riscos:**
|
|
- a raiz continua crescendo;
|
|
- domínios ficam misturados;
|
|
- incentiva acesso direto a managers internos;
|
|
- torna mais difícil explicar a API do OS;
|
|
- cada nova capability aumenta a pressão no mesmo arquivo e no mesmo objeto.
|
|
|
|
**Manutenibilidade:**
|
|
Fraca no médio prazo.
|
|
|
|
### Opcao B - Criar facades de domínio em torno do SystemOS
|
|
|
|
**Abordagem:**
|
|
Criar facades estreitas por domínio, expostas como acesso semântico:
|
|
|
|
```text
|
|
os.lifecycle().suspend_task(...)
|
|
os.fs().mount(...)
|
|
os.window().set_focus(...)
|
|
```
|
|
|
|
Ou, se o design permitir sem duplicar ownership:
|
|
|
|
```text
|
|
os.lifecycle.suspend_task(...)
|
|
os.fs.mount(...)
|
|
os.window.set_focus(...)
|
|
```
|
|
|
|
As facades seriam views/handles sobre os campos internos do `SystemOS`, não
|
|
owners independentes.
|
|
|
|
**Vantagens:**
|
|
- deixa a raiz do OS menor;
|
|
- agrupa API por domínio;
|
|
- torna mais claro o que é lifecycle, fs, window, memcard e VM;
|
|
- ajuda a esconder managers internos;
|
|
- reduz a chance de firmware coordenar detalhes por fora.
|
|
|
|
**Custos / Riscos:**
|
|
- exige decidir padrão de borrowing;
|
|
- pode adicionar tipos pequenos e boilerplate;
|
|
- `os.lifecycle.bla()` como campo direto pode ser difícil se a facade precisar
|
|
acessar `task_manager` e `process_manager` que vivem no mesmo `SystemOS`;
|
|
- talvez precise começar com métodos `os.lifecycle()` em vez de campos públicos.
|
|
|
|
**Manutenibilidade:**
|
|
Forte se as facades forem views estreitas e não novos owners.
|
|
|
|
### Opcao C - Criar services owners independentes dentro do SystemOS
|
|
|
|
**Abordagem:**
|
|
Mover estado e lógica para structs owned diretamente:
|
|
|
|
```text
|
|
SystemOS
|
|
lifecycle: LifecycleService
|
|
fs: FileSystemService
|
|
window: WindowService
|
|
```
|
|
|
|
Cada service seria owner do seu próprio estado ou de parte dele.
|
|
|
|
**Vantagens:**
|
|
- aproxima o shape desejado `os.lifecycle.bla()`;
|
|
- reduz métodos no root;
|
|
- pode simplificar alguns domínios autocontidos.
|
|
|
|
**Custos / Riscos:**
|
|
- lifecycle precisa coordenar task/process, então ownership separado pode criar
|
|
borrow/coordenação mais difícil;
|
|
- filesystem hoje cruza VM syscall state, `VirtualFS`, `FsState`, handles e
|
|
logging;
|
|
- pode reabrir decisões de ownership que acabaram de estabilizar;
|
|
- risco de mover estado cedo demais para caber numa estética de API.
|
|
|
|
**Manutenibilidade:**
|
|
Boa para domínios autocontidos, arriscada para lifecycle neste momento.
|
|
|
|
## Sugestao / Recomendacao
|
|
|
|
A direção recomendada é **Opção B: facades de domínio como views estreitas sobre
|
|
o `SystemOS`**.
|
|
|
|
O corte recomendado é:
|
|
|
|
```text
|
|
SystemOS
|
|
lifecycle()
|
|
set_foreground_task
|
|
suspend_task
|
|
resume_task
|
|
close_task
|
|
crash_task
|
|
|
|
sessions()
|
|
create_vm_game_task
|
|
create_vm_shell_task
|
|
create_native_shell_task
|
|
|
|
vm()
|
|
initialize
|
|
tick
|
|
|
|
fs()
|
|
mount
|
|
open
|
|
read
|
|
write
|
|
close
|
|
|
|
window()
|
|
add_window
|
|
set_focus
|
|
focused_window
|
|
close_window
|
|
|
|
log(...)
|
|
```
|
|
|
|
E evitar que a raiz acumule:
|
|
|
|
```text
|
|
suspend_task
|
|
resume_task
|
|
close_task
|
|
crash_task
|
|
mount_fs
|
|
initialize_vm
|
|
tick_vm
|
|
create_vm_game_task
|
|
create_vm_shell_task
|
|
create_native_shell_task
|
|
window_manager direto
|
|
task_manager direto
|
|
process_manager direto
|
|
vm_runtime direto
|
|
fs direto
|
|
memcard direto
|
|
```
|
|
|
|
Para Rust, o primeiro corte provavelmente deve usar métodos de acesso que
|
|
retornam views:
|
|
|
|
```rust
|
|
os.lifecycle().suspend_task(task_id)
|
|
os.fs().mount(backend)
|
|
os.window().set_focus(window_id)
|
|
```
|
|
|
|
Isso é menos bonito que campo direto, mas evita congelar ownership errado. Se
|
|
mais tarde algum domínio puder virar service owner real, podemos migrar para
|
|
campo direto sem mudar a semântica.
|
|
|
|
Logging pode permanecer na raiz:
|
|
|
|
```rust
|
|
os.log(...)
|
|
```
|
|
|
|
Motivo: logging é transversal, curto, usado por várias etapas do firmware, e não
|
|
carrega sozinho uma política complexa de estado.
|
|
|
|
## Perguntas em Aberto
|
|
|
|
- [x] Queremos a sintaxe ideal `os.lifecycle.bla()` mesmo que isso force
|
|
services owners reais, ou aceitamos `os.lifecycle().bla()` como primeira forma
|
|
borrow-friendly? quando escrevi os.lifecycle.bla() eu queria mesmo era os.lifecycle().bla()
|
|
- [x] Quais domínios entram no primeiro corte: só `lifecycle` e `fs`, ou também
|
|
`window`? nao precisamos criar nada, mas lifecycle, fs, window e vm sao easy wins no meu ponto de vista
|
|
- [x] `create_vm_game_task` e `create_vm_shell_task` pertencem a
|
|
`os.lifecycle()`, a `os.processes()/os.tasks()`, ou a um futuro domínio
|
|
`os.apps()/os.sessions()`? vamos de os.session() para esses.
|
|
- [x] `tick_vm` e `initialize_vm` devem ficar temporariamente na raiz, ou já
|
|
entrar em `os.vm()`? isso, os.vm().
|
|
- [x] Campos como `task_manager`, `process_manager`, `window_manager`,
|
|
`vm_runtime`, `fs`, `memcard` devem deixar de ser públicos no mesmo corte ou
|
|
em planos graduais? eu nao os deixaria publicos desde jah, isso forca a politica de facades dentro de system os.
|
|
- [x] Como preservar testes sem criar APIs públicas só para inspeção? Testes devem ser feitos nos subdomínios; SystemOS só testa composição e coordenação que não pertence isoladamente a um domínio.
|
|
|
|
## Resolucao Proposta
|
|
|
|
A agenda deve fechar pela **Opção B**.
|
|
|
|
O `SystemOS` continua sendo o owner e boundary de coordenação, mas sua superfície
|
|
pública deve ser compartimentalizada em facades de domínio. A forma normativa
|
|
inicial deve ser por métodos que retornam views borrow-friendly:
|
|
|
|
```rust
|
|
os.lifecycle().suspend_task(task_id)
|
|
os.sessions().create_vm_game_task(app_id, title)
|
|
os.vm().initialize(vm, cartridge)
|
|
os.fs().mount(backend)
|
|
os.window().set_focus(window_id)
|
|
os.log(level, source, tag, msg)
|
|
```
|
|
|
|
A sintaxe com campo direto (`os.lifecycle.suspend_task(...)`) não é requisito
|
|
deste corte. A intenção semântica é domínio explícito; a forma prática inicial
|
|
deve respeitar ownership e borrowing em Rust.
|
|
|
|
Domínios do primeiro corte:
|
|
|
|
- `lifecycle()`: lifecycle semântico de task/process.
|
|
- `sessions()`: criação de tasks/processos de jogo e shell.
|
|
- `vm()`: inicialização e tick da VM.
|
|
- `fs()`: filesystem operacional.
|
|
- `window()`: operações mínimas de janela/foco.
|
|
- `log(...)`: permanece na raiz como operação transversal.
|
|
|
|
Campos internos como `task_manager`, `process_manager`, `window_manager`,
|
|
`vm_runtime`, `fs`, `fs_state`, `memcard`, `open_files` e `next_handle` devem
|
|
deixar de ser públicos já neste corte, salvo se um plan específico demonstrar
|
|
necessidade temporária de migração. A política desejada é forçar acesso por
|
|
facades dentro do `SystemOS`.
|
|
|
|
Testes devem migrar para os subdomínios quando estiverem validando comportamento
|
|
de domínio. `SystemOS` deve testar apenas composição e coordenação que realmente
|
|
não pertence isoladamente a um domínio.
|
|
|
|
## Criterio para Encerrar
|
|
|
|
Esta agenda pode virar decisão quando fecharmos:
|
|
|
|
- qual forma de facade será normativa: campo direto, método view, ou service
|
|
owner; **resolvido: método view borrow-friendly.**
|
|
- quais domínios entram no primeiro corte;
|
|
**resolvido: lifecycle, sessions, vm, fs, window e log na raiz.**
|
|
- quais APIs permanecem no root;
|
|
**resolvido: `new`/construção e `log(...)`; demais APIs devem migrar para
|
|
facades.**
|
|
- se campos internos deixam de ser públicos agora ou em ondas;
|
|
**resolvido: deixar de ser públicos já no corte, com exceção transitória
|
|
somente se plan demonstrar necessidade.**
|
|
- como lifecycle, fs e window serão acessados por firmware, Hub e testes.
|
|
**resolvido: por facades; testes de domínio nos subdomínios.**
|
|
|
|
## Proximo Passo
|
|
|
|
Esta agenda está pronta para decisão normativa se a resolução proposta for
|
|
aceita.
|