addded PRs for fixing issues.
This commit is contained in:
parent
818e27eb31
commit
ed5d6abec9
@ -1,236 +0,0 @@
|
||||
# PR-001 Runtime Builtin Registry and Intrinsic Metadata
|
||||
|
||||
## Goal
|
||||
|
||||
Introduce the runtime-owned metadata layer required for VM-owned builtin types
|
||||
and intrinsic operations without touching the host syscall path.
|
||||
|
||||
This PR creates the semantic foundation that the frontend can target later.
|
||||
|
||||
## Why
|
||||
|
||||
Today the host-backed path already exists conceptually:
|
||||
|
||||
- canonical host identity,
|
||||
- PBX `SYSC`,
|
||||
- `HOSTCALL`,
|
||||
- loader resolution,
|
||||
- final `SYSCALL`.
|
||||
|
||||
Builtin semantics need a different ownership path:
|
||||
|
||||
- runtime-owned builtin type metadata,
|
||||
- runtime-owned intrinsic metadata,
|
||||
- flattened slot layouts,
|
||||
- and VM execution that never crosses the host boundary.
|
||||
|
||||
Without this layer, the runtime will be forced to encode builtin behavior as
|
||||
ad hoc helpers or as pseudo-syscalls, both of which conflict with the PBS model.
|
||||
|
||||
## Scope
|
||||
|
||||
Add runtime data structures and lookup APIs for:
|
||||
|
||||
- builtin type identity,
|
||||
- builtin field layout,
|
||||
- builtin constant identity,
|
||||
- intrinsic identity,
|
||||
- intrinsic stack layouts,
|
||||
- and intrinsic implementation registration.
|
||||
|
||||
Do not add bytecode execution changes in this PR.
|
||||
Do not add loader-side host changes in this PR.
|
||||
|
||||
## Required Runtime Concepts
|
||||
|
||||
### 1. Builtin type identity
|
||||
|
||||
Canonical builtin identity must be:
|
||||
|
||||
```text
|
||||
(name, version)
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
- `("color", 1)`
|
||||
- `("vec2", 1)`
|
||||
- `("pixel", 1)`
|
||||
|
||||
This is distinct from source-visible PBS names such as `Color` or `Vec2`.
|
||||
|
||||
### 2. Builtin layout descriptor
|
||||
|
||||
Introduce a runtime descriptor roughly shaped like:
|
||||
|
||||
```text
|
||||
BuiltinTypeMeta {
|
||||
id: u32
|
||||
name: string
|
||||
version: u16
|
||||
fields: [BuiltinFieldMeta]
|
||||
flat_slot_layout: [AbiType]
|
||||
flat_slot_width: u16
|
||||
}
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```text
|
||||
BuiltinFieldMeta {
|
||||
name: string
|
||||
start_slot: u16
|
||||
field_type: BuiltinLayoutType
|
||||
flat_slot_width: u16
|
||||
}
|
||||
```
|
||||
|
||||
`BuiltinLayoutType` should support:
|
||||
|
||||
- fixed-width scalar runtime types,
|
||||
- builtin nominal type references,
|
||||
- and recursively flattenable aggregate builtin layouts.
|
||||
|
||||
### 3. Builtin constant descriptor
|
||||
|
||||
Introduce a constant registry keyed by:
|
||||
|
||||
```text
|
||||
(target, name, version)
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
- `("vec2", "zero", 1)`
|
||||
|
||||
This registry must return either:
|
||||
|
||||
- direct materialization metadata,
|
||||
- or a runtime-owned constant implementation hook.
|
||||
|
||||
### 4. Intrinsic descriptor
|
||||
|
||||
Introduce an intrinsic registry keyed by:
|
||||
|
||||
```text
|
||||
(owner, name, version)
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
- `("vec2", "dot", 1)`
|
||||
- `("vec2", "length", 1)`
|
||||
|
||||
Descriptor shape should include at minimum:
|
||||
|
||||
```text
|
||||
IntrinsicMeta {
|
||||
id: u32
|
||||
owner: string
|
||||
name: string
|
||||
version: u16
|
||||
arg_layout: [AbiType]
|
||||
ret_layout: [AbiType]
|
||||
deterministic: bool
|
||||
may_allocate: bool
|
||||
}
|
||||
```
|
||||
|
||||
## Design Rules
|
||||
|
||||
1. This registry is runtime-owned, not host-owned.
|
||||
2. It must not reuse `SYSC`.
|
||||
3. It must not depend on capability grants.
|
||||
4. It must not resolve through the host syscall registry.
|
||||
5. It must preserve flattened slot width for verifier and executor use.
|
||||
6. It must preserve nominal builtin identity even when two builtins share the same width.
|
||||
|
||||
## Representation Guidance
|
||||
|
||||
### Scalars
|
||||
|
||||
Support at least:
|
||||
|
||||
- `int`
|
||||
- `float`
|
||||
- `bool`
|
||||
- builtin nominal scalars such as `color`
|
||||
|
||||
For nominal scalars like `color`, allow either:
|
||||
|
||||
- a dedicated runtime value variant,
|
||||
- or a 1-slot carrier with explicit builtin type tagging in metadata.
|
||||
|
||||
The important requirement is that `color` remain semantically distinct from a
|
||||
plain `int` even if it shares width.
|
||||
|
||||
### Aggregates
|
||||
|
||||
Builtin aggregates such as `vec2` and `pixel` should remain stack-shaped.
|
||||
|
||||
The registry must treat them as:
|
||||
|
||||
- fixed-width,
|
||||
- finite,
|
||||
- flattenable,
|
||||
- and non-heap in this phase.
|
||||
|
||||
No heap object model is required.
|
||||
|
||||
## Suggested API Surface
|
||||
|
||||
Introduce runtime APIs along these lines:
|
||||
|
||||
- `lookup_builtin_type(name, version) -> BuiltinTypeMeta`
|
||||
- `lookup_builtin_constant(target, name, version) -> BuiltinConstMeta`
|
||||
- `lookup_intrinsic(owner, name, version) -> IntrinsicMeta`
|
||||
- `lookup_intrinsic_by_id(id) -> IntrinsicMeta`
|
||||
|
||||
Avoid exposing host-like resolution APIs for this subsystem.
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- `INTRINSIC` opcode execution
|
||||
- `INTRCALL` preload resolution
|
||||
- loader patching
|
||||
- frontend lowering
|
||||
- host integration
|
||||
- HAL color adaptation
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. Runtime contains a distinct builtin/intrinsic registry subsystem.
|
||||
2. Registry keys use canonical builtin and intrinsic identities, not source aliases.
|
||||
3. Builtin layouts support recursive flattening and expose total flat slot width.
|
||||
4. Builtin constants have a dedicated registry keyed separately from intrinsics.
|
||||
5. No part of the implementation routes through host syscall metadata.
|
||||
6. Unit tests cover lookup and flattening for `color`, `vec2`, and `pixel`.
|
||||
|
||||
## Test Cases
|
||||
|
||||
### Builtin layout flattening
|
||||
|
||||
- `color` flattens to width `1`
|
||||
- `vec2` flattens to width `2`
|
||||
- `pixel(x: int, y: int, color: color)` flattens to width `3`
|
||||
|
||||
### Nested field offsets
|
||||
|
||||
- `vec2.x` starts at slot `0`
|
||||
- `vec2.y` starts at slot `1`
|
||||
- `pixel.color` starts at slot `2`
|
||||
|
||||
### Intrinsic metadata
|
||||
|
||||
- `vec2.dot` has arg width `4` and ret width `1`
|
||||
- `vec2.length` has arg width `2` and ret width `1`
|
||||
|
||||
## Notes for Follow-up PRs
|
||||
|
||||
This PR should intentionally stop short of execution.
|
||||
|
||||
The next PR should consume these descriptors in:
|
||||
|
||||
- bytecode decoding,
|
||||
- verifier stack-effect calculation,
|
||||
- and runtime dispatch for `INTRINSIC <id>`.
|
||||
@ -1,168 +0,0 @@
|
||||
# PR-002 Runtime INTRINSIC Opcode, Verification, and Dispatch
|
||||
|
||||
## Goal
|
||||
|
||||
Add a dedicated runtime execution path for VM-owned intrinsics using the
|
||||
metadata introduced in PR-001.
|
||||
|
||||
This PR should establish that intrinsic execution is a first-class VM path,
|
||||
separate from host-backed syscall execution.
|
||||
|
||||
## Why
|
||||
|
||||
The runtime currently has a conceptual host-backed path centered on `SYSCALL`.
|
||||
Builtin semantics cannot be layered cleanly on top of that path because:
|
||||
|
||||
- intrinsic ownership is VM-owned, not host-owned,
|
||||
- intrinsic execution must not require host resolution,
|
||||
- intrinsic execution must not depend on capabilities,
|
||||
- and verifier stack effects must come from builtin layout metadata.
|
||||
|
||||
The runtime therefore needs its own instruction and dispatch path.
|
||||
|
||||
## MVP Decision
|
||||
|
||||
This PR should implement direct final-form execution:
|
||||
|
||||
```text
|
||||
INTRINSIC <id>
|
||||
```
|
||||
|
||||
Do not implement `INTRCALL` in this PR unless the runtime already has a clear
|
||||
preload declaration mechanism that can be reused without coupling to `SYSC`.
|
||||
|
||||
The intent is:
|
||||
|
||||
- keep the runtime simple,
|
||||
- let the frontend eventually emit final intrinsic ids for a selected VM line,
|
||||
- and avoid pulling loader complexity into the first implementation.
|
||||
|
||||
## Scope
|
||||
|
||||
Add:
|
||||
|
||||
- runtime opcode support for `INTRINSIC <id>`,
|
||||
- verifier support for intrinsic stack effects,
|
||||
- execution dispatch by intrinsic id,
|
||||
- trap behavior for unknown intrinsic ids,
|
||||
- and tests proving separation from the syscall pipeline.
|
||||
|
||||
Do not add host loader changes in this PR.
|
||||
|
||||
## Required Changes
|
||||
|
||||
### 1. Bytecode/ISA support
|
||||
|
||||
Introduce a dedicated intrinsic opcode in the runtime bytecode interpreter.
|
||||
|
||||
Normative behavior:
|
||||
|
||||
- decode `INTRINSIC <id>`,
|
||||
- lookup intrinsic metadata by numeric id,
|
||||
- verify or assume verifier-proven stack shape,
|
||||
- execute runtime-owned implementation,
|
||||
- push results back according to intrinsic return layout.
|
||||
|
||||
### 2. Verifier support
|
||||
|
||||
The verifier must derive intrinsic stack effects from runtime intrinsic metadata.
|
||||
|
||||
Required behavior:
|
||||
|
||||
- lookup intrinsic meta by id,
|
||||
- compute argument slot width from flattened `arg_layout`,
|
||||
- compute result slot width from flattened `ret_layout`,
|
||||
- reject underflow,
|
||||
- reject invalid slot shape,
|
||||
- and preserve existing verifier guarantees for control flow.
|
||||
|
||||
Examples:
|
||||
|
||||
- `vec2.dot(vec2, vec2) -> float` becomes `pop 4, push 1`
|
||||
- `vec2.length(vec2) -> float` becomes `pop 2, push 1`
|
||||
|
||||
### 3. Trap behavior
|
||||
|
||||
Add deterministic failure for:
|
||||
|
||||
- unknown intrinsic id,
|
||||
- malformed intrinsic metadata,
|
||||
- verifier/runtime disagreement on intrinsic width,
|
||||
- and execution-time misuse that escapes verifier guarantees.
|
||||
|
||||
If trap enums exist, add a runtime-specific invalid intrinsic trap rather than
|
||||
reusing invalid syscall traps.
|
||||
|
||||
### 4. Dispatch separation
|
||||
|
||||
Ensure the interpreter or executor has two clearly distinct paths:
|
||||
|
||||
- `SYSCALL <id>` for host-backed services
|
||||
- `INTRINSIC <id>` for VM-owned semantics
|
||||
|
||||
These paths must not share registry lookup semantics.
|
||||
|
||||
## Suggested Runtime Shape
|
||||
|
||||
Use a structure roughly like:
|
||||
|
||||
```text
|
||||
execute_intrinsic(id, stack, runtime_ctx) -> Result<(), Trap>
|
||||
```
|
||||
|
||||
where:
|
||||
|
||||
- `stack` is mutated using metadata-defined widths,
|
||||
- `runtime_ctx` is VM-internal context only,
|
||||
- and no host syscall registry access occurs.
|
||||
|
||||
If an execution table already exists for opcodes, add intrinsic dispatch as a
|
||||
parallel branch rather than as a host-call subtype.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. Runtime recognizes and executes `INTRINSIC <id>`.
|
||||
2. Verifier derives stack effects from intrinsic metadata rather than hardcoded arity alone.
|
||||
3. Unknown intrinsic ids fail deterministically.
|
||||
4. `INTRINSIC` does not route through host binding, loader syscall resolution, or capability checks.
|
||||
5. `SYSCALL` behavior remains unchanged.
|
||||
6. Tests demonstrate that intrinsic execution and syscall execution are distinct runtime paths.
|
||||
|
||||
## Test Cases
|
||||
|
||||
### Positive
|
||||
|
||||
- execute `vec2.dot` over two canonical `vec2` values and obtain one float result
|
||||
- execute `vec2.length` over one canonical `vec2` value and obtain one float result
|
||||
|
||||
### Verification
|
||||
|
||||
- verifier accepts a correct stack program using `INTRINSIC <vec2.dot>`
|
||||
- verifier rejects a program with insufficient stack width for `INTRINSIC <vec2.dot>`
|
||||
|
||||
### Separation
|
||||
|
||||
- `SYSCALL` still resolves and executes host-backed operations as before
|
||||
- invalid intrinsic id produces intrinsic-specific failure, not syscall failure
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- frontend parser/lowering changes
|
||||
- preload `INTRCALL` resolution
|
||||
- builtin constant source lowering
|
||||
- new host bindings
|
||||
|
||||
## Notes for Follow-up PRs
|
||||
|
||||
The next PR should populate the registry and executor with the first builtin
|
||||
set:
|
||||
|
||||
- `color`
|
||||
- `vec2`
|
||||
- `pixel`
|
||||
|
||||
and with first intrinsic implementations:
|
||||
|
||||
- `vec2.dot`
|
||||
- `vec2.length`
|
||||
- optionally `vec2.distance`
|
||||
@ -1,273 +0,0 @@
|
||||
# PR-003 Runtime First Builtins: Color, Vec2, Pixel
|
||||
|
||||
## Goal
|
||||
|
||||
Implement the first concrete builtin types, constants, and intrinsic behaviors
|
||||
so the frontend can target a stable MVP builtin line.
|
||||
|
||||
This PR should be the first runtime feature slice that a PBS frontend can map
|
||||
to directly.
|
||||
|
||||
## Why
|
||||
|
||||
After PR-001 and PR-002, the runtime has the machinery but not the domain set.
|
||||
This PR makes the model real by installing the first builtin registry entries
|
||||
and execution implementations.
|
||||
|
||||
The initial scope should match the current agenda and spec direction:
|
||||
|
||||
- scalar builtin `color`
|
||||
- aggregate builtin `vec2`
|
||||
- aggregate builtin `pixel`
|
||||
- intrinsic methods for `vec2`
|
||||
- builtin constant for `vec2.zero`
|
||||
|
||||
## Scope
|
||||
|
||||
Add runtime registry entries and implementations for:
|
||||
|
||||
- builtin type `color`
|
||||
- builtin type `vec2`
|
||||
- builtin type `pixel`
|
||||
- builtin constant `("vec2", "zero", 1)`
|
||||
- intrinsic `("vec2", "dot", 1)`
|
||||
- intrinsic `("vec2", "length", 1)`
|
||||
|
||||
`("vec2", "distance", 1)` may be included if the numeric contract is already
|
||||
clear enough for portable behavior.
|
||||
If not, leave it for a follow-up PR.
|
||||
|
||||
## Builtin Type Contracts
|
||||
|
||||
### 1. `color`
|
||||
|
||||
Canonical identity:
|
||||
|
||||
```text
|
||||
("color", 1)
|
||||
```
|
||||
|
||||
Expected properties:
|
||||
|
||||
- scalar builtin
|
||||
- flat slot width `1`
|
||||
- runtime semantic distinctness from plain `int`
|
||||
|
||||
Suggested field model:
|
||||
|
||||
- `raw` carrier field if the runtime benefits from explicit internal naming
|
||||
|
||||
### 2. `vec2`
|
||||
|
||||
Canonical identity:
|
||||
|
||||
```text
|
||||
("vec2", 1)
|
||||
```
|
||||
|
||||
Expected properties:
|
||||
|
||||
- aggregate builtin
|
||||
- flattened layout `[float, float]`
|
||||
- field `x` at slot `0`
|
||||
- field `y` at slot `1`
|
||||
- flat slot width `2`
|
||||
|
||||
### 3. `pixel`
|
||||
|
||||
Canonical identity:
|
||||
|
||||
```text
|
||||
("pixel", 1)
|
||||
```
|
||||
|
||||
Expected properties:
|
||||
|
||||
- aggregate builtin
|
||||
- semantic layout `[int, int, color]`
|
||||
- flattened width `3`
|
||||
- field `x` at slot `0`
|
||||
- field `y` at slot `1`
|
||||
- field `color` at slot `2`
|
||||
|
||||
## Builtin Constant Contract
|
||||
|
||||
### `vec2.zero`
|
||||
|
||||
Canonical identity:
|
||||
|
||||
```text
|
||||
("vec2", "zero", 1)
|
||||
```
|
||||
|
||||
Expected materialized value:
|
||||
|
||||
```text
|
||||
[0.0, 0.0]
|
||||
```
|
||||
|
||||
This constant must be runtime-owned and materialized without touching the host.
|
||||
|
||||
## Intrinsic Contracts
|
||||
|
||||
### 1. `vec2.dot`
|
||||
|
||||
Canonical identity:
|
||||
|
||||
```text
|
||||
("vec2", "dot", 1)
|
||||
```
|
||||
|
||||
Stack contract:
|
||||
|
||||
```text
|
||||
args: [float, float, float, float]
|
||||
ret: [float]
|
||||
```
|
||||
|
||||
Semantic behavior:
|
||||
|
||||
```text
|
||||
(x1 * x2) + (y1 * y2)
|
||||
```
|
||||
|
||||
### 2. `vec2.length`
|
||||
|
||||
Canonical identity:
|
||||
|
||||
```text
|
||||
("vec2", "length", 1)
|
||||
```
|
||||
|
||||
Stack contract:
|
||||
|
||||
```text
|
||||
args: [float, float]
|
||||
ret: [float]
|
||||
```
|
||||
|
||||
Semantic behavior:
|
||||
|
||||
```text
|
||||
sqrt((x * x) + (y * y))
|
||||
```
|
||||
|
||||
### 3. Optional: `vec2.distance`
|
||||
|
||||
Canonical identity:
|
||||
|
||||
```text
|
||||
("vec2", "distance", 1)
|
||||
```
|
||||
|
||||
Stack contract:
|
||||
|
||||
```text
|
||||
args: [float, float, float, float]
|
||||
ret: [float]
|
||||
```
|
||||
|
||||
Semantic behavior:
|
||||
|
||||
```text
|
||||
sqrt(((x1 - x2)^2) + ((y1 - y2)^2))
|
||||
```
|
||||
|
||||
Only include this if the runtime already has a clear portable numeric contract
|
||||
for `sqrt`.
|
||||
|
||||
## Representation Guidance
|
||||
|
||||
### `color`
|
||||
|
||||
Choose one of:
|
||||
|
||||
1. dedicated scalar runtime variant with builtin nominal tag
|
||||
2. 1-slot scalar carrier plus explicit builtin registry identity
|
||||
|
||||
The critical rule is:
|
||||
|
||||
- `color` must remain semantically a builtin color type,
|
||||
- even if its carrier width matches `int`.
|
||||
|
||||
### `vec2` and `pixel`
|
||||
|
||||
Do not allocate heap objects for these in the MVP.
|
||||
|
||||
Represent them as:
|
||||
|
||||
- canonical stack-shaped flattened values,
|
||||
- with runtime metadata describing field offsets and nominal builtin identity.
|
||||
|
||||
## Numeric Contract Note
|
||||
|
||||
`vec2.dot` is straightforward and should land in this PR.
|
||||
|
||||
`vec2.length` and `vec2.distance` depend on the runtime's floating-point
|
||||
portability story. If that story is not already stable, implement:
|
||||
|
||||
1. `vec2.dot`
|
||||
2. `vec2.zero`
|
||||
3. builtin type descriptors for `color`, `vec2`, `pixel`
|
||||
|
||||
and either:
|
||||
|
||||
- gate `length`/`distance` behind the current platform float rules,
|
||||
- or defer them into a follow-up PR.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. Runtime registry contains builtin entries for `color`, `vec2`, and `pixel`.
|
||||
2. Runtime registry contains builtin constant entry for `("vec2", "zero", 1)`.
|
||||
3. Runtime registry contains intrinsic entries for at least `vec2.dot` and `vec2.length`.
|
||||
4. `vec2` layout is width `2` and `pixel` layout is width `3`.
|
||||
5. `pixel` composes `color` through builtin layout metadata rather than by special-case host code.
|
||||
6. Executing `vec2.dot` and `vec2.length` through `INTRINSIC <id>` produces correct runtime results.
|
||||
7. No part of the implementation routes through `SYSC`, `HOSTCALL`, or `SYSCALL`.
|
||||
|
||||
## Test Cases
|
||||
|
||||
### Builtin metadata
|
||||
|
||||
- `color` width is `1`
|
||||
- `vec2` width is `2`
|
||||
- `pixel` width is `3`
|
||||
|
||||
### Constant materialization
|
||||
|
||||
- materializing `("vec2", "zero", 1)` yields `[0.0, 0.0]`
|
||||
|
||||
### Intrinsic execution
|
||||
|
||||
- `dot([1, 2], [3, 4]) == 11`
|
||||
- `length([3, 4]) == 5`
|
||||
|
||||
### Composition
|
||||
|
||||
- `pixel(x=1, y=2, color=<red>)` uses builtin metadata width `3`
|
||||
- `pixel.color` points at slot `2`
|
||||
|
||||
## Frontend Alignment
|
||||
|
||||
This PR should be implemented so the following frontend surfaces map naturally:
|
||||
|
||||
```pbs
|
||||
[BuiltinType(name="vec2", version=1)]
|
||||
declare builtin type Vec2(
|
||||
[Slot(0)] pub x: float,
|
||||
[Slot(1)] pub y: float,
|
||||
) {
|
||||
[IntrinsicCall(name="dot")]
|
||||
fn dot(other: Vec2) -> float;
|
||||
|
||||
[IntrinsicCall(name="length")]
|
||||
fn length() -> float;
|
||||
}
|
||||
|
||||
[BuiltinConst(target="vec2", name="zero", version=1)]
|
||||
declare const ZERO: Vec2;
|
||||
```
|
||||
|
||||
The runtime should not care whether the source-visible type name is `Vec2`,
|
||||
`vec2`, or something else.
|
||||
It should care only about canonical identities and flattened layout.
|
||||
@ -0,0 +1,102 @@
|
||||
# PR-004: Runtime VFS Path Traversal Hardening
|
||||
|
||||
## Briefing
|
||||
|
||||
Hoje o `VirtualFS` normaliza barras, mas nao canonicaliza nem rejeita segmentos `..`. Em seguida, o backend de host concatena o caminho recebido com a raiz montada. Isso abre espaco para escapar da raiz virtual com caminhos como `/user/../../outside.txt`.
|
||||
|
||||
Este PR endurece a fronteira entre o filesystem virtual e o filesystem do host. O objetivo e garantir que toda operacao de `read/write/delete/list/exists` permaneça estritamente dentro da raiz montada.
|
||||
|
||||
## Problema
|
||||
|
||||
- O `VirtualFS` aceita caminhos relativos e absolutos sem validacao estrutural suficiente.
|
||||
- O backend `HostDirBackend` faz `root.join(path)` sem bloquear traversal.
|
||||
- O problema afeta confidencialidade, integridade e isolamento do runtime.
|
||||
|
||||
## Escopo
|
||||
|
||||
- Endurecer a normalizacao de caminhos no `VirtualFS`.
|
||||
- Endurecer a resolucao no `HostDirBackend`.
|
||||
- Garantir comportamento consistente para `read_file`, `write_file`, `delete`, `list_dir` e `exists`.
|
||||
- Cobrir casos de traversal em testes unitarios.
|
||||
|
||||
## Fora de Escopo
|
||||
|
||||
- Suporte a links simbolicos com politicas avancadas.
|
||||
- Politicas de permissao por namespace (`/system`, `/user`, `/apps`, etc).
|
||||
- Refactor completo da API de filesystem.
|
||||
|
||||
## Abordagem
|
||||
|
||||
1. Introduzir uma regra unica de validacao de caminho virtual:
|
||||
- converter `\` para `/`;
|
||||
- exigir caminho absoluto virtual;
|
||||
- colapsar `.` quando aparecer;
|
||||
- rejeitar qualquer segmento vazio ambiguo ou `..`;
|
||||
- retornar erro explicito em vez de tentar "corrigir" traversal.
|
||||
2. Fazer o `VirtualFS` operar apenas sobre caminhos validados.
|
||||
3. Endurecer o `HostDirBackend` para nunca confiar apenas na normalizacao acima:
|
||||
- resolver o caminho relativo a partir da raiz;
|
||||
- rejeitar novamente qualquer tentativa de escapar;
|
||||
- manter defesa em profundidade mesmo se outro backend ou chamador evoluir errado.
|
||||
4. Garantir que operacoes booleanas como `exists` nao silenciem traversal como se fosse "arquivo inexistente" sem distinguir erro estrutural quando isso for relevante para a API.
|
||||
|
||||
## Algoritmo
|
||||
|
||||
### Normalizacao de caminho virtual
|
||||
|
||||
Entrada: `path: &str`
|
||||
|
||||
Saida: caminho virtual sanitizado ou erro.
|
||||
|
||||
Passos:
|
||||
|
||||
1. Substituir `\` por `/`.
|
||||
2. Se o caminho nao comecar com `/`, prefixar `/`.
|
||||
3. Separar por `/`.
|
||||
4. Ignorar segmentos vazios e `.`.
|
||||
5. Se algum segmento for `..`, falhar com `FsError`.
|
||||
6. Reconstruir o caminho como `/<seg1>/<seg2>/...`.
|
||||
7. Preservar `/` como raiz quando nao houver segmentos.
|
||||
|
||||
### Resolucao no backend do host
|
||||
|
||||
Entrada: caminho virtual sanitizado.
|
||||
|
||||
Saida: `PathBuf` dentro de `root` ou erro.
|
||||
|
||||
Passos:
|
||||
|
||||
1. Remover o `/` inicial do caminho virtual.
|
||||
2. Concatenar cada segmento validado manualmente em um `PathBuf` iniciado em `root`.
|
||||
3. Nunca aceitar segmentos `..`, `.` ou componentes de prefixo/plataforma.
|
||||
4. Antes de retornar, garantir que o caminho construido continua sob `root`.
|
||||
|
||||
## Criterios de Aceite
|
||||
|
||||
- Qualquer tentativa de traversal com `..` e rejeitada em `read_file`.
|
||||
- Qualquer tentativa de traversal com `..` e rejeitada em `write_file`.
|
||||
- Qualquer tentativa de traversal com `..` e rejeitada em `delete`.
|
||||
- `exists` e `list_dir` nao acessam caminhos fora da raiz montada.
|
||||
- Caminhos normais como `/user/save.dat` continuam funcionando.
|
||||
- O backend de host continua criando subdiretorios validos dentro da raiz.
|
||||
|
||||
## Tests
|
||||
|
||||
- Teste unitario no `VirtualFS` para rejeitar:
|
||||
- `../x`
|
||||
- `/../x`
|
||||
- `/user/../../x`
|
||||
- `\\user\\..\\..\\x`
|
||||
- Teste unitario no backend do host validando que um caminho de traversal nao resulta em acesso fora da raiz temporaria.
|
||||
- Teste positivo para operacoes validas:
|
||||
- criar arquivo em `/user/test.txt`;
|
||||
- ler o mesmo arquivo;
|
||||
- confirmar `exists`;
|
||||
- apagar o arquivo.
|
||||
- Rodar:
|
||||
- `cargo test -p prometeu-system`
|
||||
- `cargo test -p prometeu-host-desktop-winit`
|
||||
|
||||
## Risco
|
||||
|
||||
Baixo para a arquitetura e medio para compatibilidade, porque caminhos hoje aceitos de forma permissiva podem passar a falhar explicitamente. Esse endurecimento e desejado.
|
||||
@ -0,0 +1,87 @@
|
||||
# PR-005: Host Audio Fallible Init and Headless Tolerance
|
||||
|
||||
## Briefing
|
||||
|
||||
O host desktop atual assume que audio de saida esta sempre disponivel e funcional. Em ambientes headless, CI, VMs remotas ou sistemas sem device compativel, a inicializacao usa `expect(...)` e encerra o processo.
|
||||
|
||||
Este PR torna a pilha de audio tolerante a falhas de infraestrutura. O runtime deve continuar operando sem audio quando o host nao puder inicializar a saida sonora.
|
||||
|
||||
## Problema
|
||||
|
||||
- `default_output_device()` pode retornar `None`.
|
||||
- `build_output_stream(...)` pode falhar por formato/configuracao.
|
||||
- `stream.play()` pode falhar por indisponibilidade do backend.
|
||||
- Todas essas falhas hoje derrubam o binario com `panic!`.
|
||||
|
||||
## Escopo
|
||||
|
||||
- Trocar inicializacao panica por API fallible.
|
||||
- Permitir degradacao controlada para "sem audio".
|
||||
- Manter telemetria/log suficiente para diagnostico.
|
||||
- Cobrir o fluxo em testes de unidade onde viavel.
|
||||
|
||||
## Fora de Escopo
|
||||
|
||||
- Rework do mixer.
|
||||
- Selecao automatica de formatos de audio mais sofisticada.
|
||||
- Hot-reload de device de audio.
|
||||
- Simulacao de audio em buffer offline.
|
||||
|
||||
## Abordagem
|
||||
|
||||
1. Mudar `HostAudio::init` para retornar `Result<(), HostAudioError>` ou tipo equivalente.
|
||||
2. Representar explicitamente o estado "audio indisponivel":
|
||||
- `producer = None`
|
||||
- `stream = None`
|
||||
- stats continuam funcionando sem crash.
|
||||
3. No chamador, registrar aviso e seguir execucao sem audio.
|
||||
4. Garantir que `send_commands` e `update_stats` sejam no-op seguros quando o audio nao estiver ativo.
|
||||
|
||||
## Algoritmo
|
||||
|
||||
### Inicializacao
|
||||
|
||||
1. Buscar `default_output_device`.
|
||||
2. Se nao existir:
|
||||
- retornar erro de inicializacao controlado.
|
||||
3. Tentar construir `StreamConfig` e `build_output_stream`.
|
||||
4. Se falhar:
|
||||
- retornar erro controlado sem panicar.
|
||||
5. Tentar `play()`.
|
||||
6. Se falhar:
|
||||
- retornar erro controlado sem panicar.
|
||||
7. Apenas em caso de sucesso preencher `producer`, `perf_consumer` e `_stream`.
|
||||
|
||||
### Degradacao
|
||||
|
||||
1. O host chama `init`.
|
||||
2. Se `Ok`, audio ativo.
|
||||
3. Se `Err`, loga a falha e continua sem audio.
|
||||
4. O loop principal segue responsivo e funcional.
|
||||
|
||||
## Criterios de Aceite
|
||||
|
||||
- O runtime nao entra em `panic!` quando nao existe device de audio.
|
||||
- O runtime nao entra em `panic!` quando `build_output_stream` falha.
|
||||
- O runtime nao entra em `panic!` quando `play()` falha.
|
||||
- `send_commands` e `update_stats` continuam seguros sem stream ativo.
|
||||
- O host continua executando cartridge em modo sem audio.
|
||||
- Logs deixam claro por que o audio foi desativado.
|
||||
|
||||
## Tests
|
||||
|
||||
- Introduzir testes de unidade para o estado sem audio:
|
||||
- `send_commands` nao falha quando `producer` e `None`;
|
||||
- `update_stats` nao falha quando `perf_consumer` e `None`.
|
||||
- Se a estrutura atual permitir injecao de dependencia:
|
||||
- testar caminho `no output device`;
|
||||
- testar falha na criacao do stream;
|
||||
- testar falha no `play`.
|
||||
- Se injecao ainda nao existir, criar uma camada minima de abstracao para tornar esses cenarios testaveis sem depender do hardware real.
|
||||
- Rodar:
|
||||
- `cargo test -p prometeu-host-desktop-winit`
|
||||
- `cargo test --workspace`
|
||||
|
||||
## Risco
|
||||
|
||||
Baixo. A mudanca principal e de robustez operacional. O maior cuidado e nao esconder a falha completamente; o modo sem audio precisa ser explicito em logs.
|
||||
72
docs/pull-requests/PR-006-cli-preserve-child-exit-status.md
Normal file
72
docs/pull-requests/PR-006-cli-preserve-child-exit-status.md
Normal file
@ -0,0 +1,72 @@
|
||||
# PR-006: CLI Preserve Child Exit Status
|
||||
|
||||
## Briefing
|
||||
|
||||
O wrapper `prometeu` despacha para outros binarios do ecossistema. Hoje, se o processo filho terminar sem exit code convencional, o CLI usa `unwrap_or(0)` e pode reportar sucesso mesmo quando houve abort, sinal ou encerramento anormal.
|
||||
|
||||
Este PR corrige a propagacao de status do processo filho para tornar o CLI confiavel em automacao, CI e uso por scripts.
|
||||
|
||||
## Problema
|
||||
|
||||
- `status.code()` pode retornar `None`.
|
||||
- `unwrap_or(0)` transforma falha anormal em sucesso.
|
||||
- Isso mascara erros reais em `run`, `debug`, `build` e `verify`.
|
||||
|
||||
## Escopo
|
||||
|
||||
- Preservar corretamente o resultado do processo filho.
|
||||
- Melhorar a mensagem de erro quando nao houver codigo numerico.
|
||||
- Cobrir o comportamento com testes.
|
||||
|
||||
## Fora de Escopo
|
||||
|
||||
- Reestruturar todo o dispatcher.
|
||||
- Implementar subcomandos ainda nao existentes.
|
||||
- Alterar o protocolo entre CLI e bins filhos.
|
||||
|
||||
## Abordagem
|
||||
|
||||
1. Remover `unwrap_or(0)` no ponto de saida.
|
||||
2. Tratar dois casos:
|
||||
- filho retorna exit code numerico: repassar exatamente;
|
||||
- filho termina sem codigo numerico: encerrar com codigo nao-zero e mensagem clara.
|
||||
3. Se necessario, extrair a traducao de `ExitStatus` para uma funcao pequena e testavel.
|
||||
|
||||
## Algoritmo
|
||||
|
||||
Entrada: `ExitStatus` do processo filho.
|
||||
|
||||
Passos:
|
||||
|
||||
1. Chamar `status.code()`.
|
||||
2. Se retornar `Some(code)`:
|
||||
- encerrar o wrapper com `code`.
|
||||
3. Se retornar `None`:
|
||||
- escrever mensagem de erro indicando encerramento anormal;
|
||||
- encerrar o wrapper com `1`.
|
||||
|
||||
## Criterios de Aceite
|
||||
|
||||
- Se o processo filho sair com `0`, o wrapper sai com `0`.
|
||||
- Se o processo filho sair com codigo nao-zero, o wrapper replica o mesmo codigo.
|
||||
- Se o processo filho terminar sem codigo numerico, o wrapper sai com codigo nao-zero.
|
||||
- O comportamento fica coberto por teste unitario.
|
||||
|
||||
## Tests
|
||||
|
||||
- Extrair funcao pura ou quase pura para mapear `ExitStatus -> i32` e testá-la.
|
||||
- Cobrir:
|
||||
- `0`;
|
||||
- `1`;
|
||||
- outro codigo nao-zero;
|
||||
- status sem code numerico quando a plataforma permitir criar esse caso em teste.
|
||||
- Se o caso `None` depender de plataforma:
|
||||
- encapsular sob `cfg(unix)` ou `cfg(windows)` conforme apropriado;
|
||||
- manter ao menos o contrato da funcao testado por unidade.
|
||||
- Rodar:
|
||||
- `cargo test -p prometeu-cli`
|
||||
- `cargo test --workspace`
|
||||
|
||||
## Risco
|
||||
|
||||
Muito baixo. A mudanca corrige semantica operacional do CLI e tende a melhorar observabilidade sem alterar a logica de dispatch.
|
||||
@ -1,18 +1,35 @@
|
||||
# Runtime PR Series for VM-owned Builtins and Intrinsics
|
||||
# Pull Requests
|
||||
|
||||
This directory contains proposed pull requests for implementing VM-owned builtin
|
||||
types and intrinsic execution in the runtime.
|
||||
Este diretório armazena propostas de PRs arquiteturais e de implementação para o runtime.
|
||||
|
||||
The series is designed so that the frontend model described in:
|
||||
## Padrão
|
||||
|
||||
- [6. VM-owned vs Host-backed](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/pbs/6.%20VM-owned%20vs%20Host-backed.md)
|
||||
- [6.1. Intrinsics and Builtin Types Specification](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/pbs/6.1.%20Intrinsics%20and%20Builtin%20Types%20Specification.md)
|
||||
- [PBS Intrinsics and Builtin Types Agenda](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/agendas/PBS%20Intrinsics%20and%20Builtin%20Types%20Agenda.md)
|
||||
Toda PR neste diretório deve ser autocontida.
|
||||
|
||||
can lower cleanly into the runtime without reusing the host syscall pipeline.
|
||||
Cada documento deve incluir, no mínimo:
|
||||
|
||||
Recommended order:
|
||||
- `Briefing`
|
||||
- `Alvo`
|
||||
- `Critérios de Aceite`
|
||||
- `Tests`, quando necessário
|
||||
|
||||
1. [PR-001 Runtime Builtin Registry and Intrinsic Metadata](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/pull-requests/PR-001-runtime-builtin-registry-and-intrinsic-metadata.md)
|
||||
2. [PR-002 Runtime INTRINSIC Opcode, Verification, and Dispatch](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/pull-requests/PR-002-runtime-intrinsic-opcode-verification-and-dispatch.md)
|
||||
3. [PR-003 Runtime First Builtins: Color, Vec2, Pixel](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/pull-requests/PR-003-runtime-first-builtins-color-vec2-pixel.md)
|
||||
## Barra de Qualidade
|
||||
|
||||
O padrão esperado é JVM-grade.
|
||||
|
||||
Isso implica:
|
||||
|
||||
- arquitetura vem antes de implementação;
|
||||
- decisões arquiteturais não devem ser tomadas durante a fase de implementação;
|
||||
- quando a implementação encontrar dúvida arquitetural, a PR deve voltar para discussão de arquitetura;
|
||||
- diante de ambiguidade estrutural, é preferível interromper a execução da PR e levantar um questionamento severo do que cristalizar uma decisão errada no código.
|
||||
|
||||
## Condução
|
||||
|
||||
Uma PR deste diretório deve:
|
||||
|
||||
- definir claramente o problema;
|
||||
- delimitar o alvo da mudança;
|
||||
- explicitar o que está fora de escopo quando houver risco de expansão;
|
||||
- estabelecer critérios objetivos de aceite;
|
||||
- definir a estratégia de teste proporcional ao risco da mudança.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user