290 lines
17 KiB
Markdown
290 lines
17 KiB
Markdown
# Phase 0.8R offline remediation and evidence contract
|
|
|
|
Decision: **READ_ONLY_PREFLIGHT_BLOCKED**.
|
|
|
|
## Scope
|
|
|
|
Phase 0.8R is documentation, evidence-contract design, and host-only
|
|
regression protection. It does not contact a PS5, observe hardware, implement
|
|
a collector, build a target artifact, transfer a file, install a component, or
|
|
execute code on a target.
|
|
|
|
It grants no authority. `installation_authorized=false`,
|
|
`lifecycle_authorized=false`, `execution_authorized=false`,
|
|
`transfer_authorized=false`, and `automatic_retry=false`.
|
|
|
|
The absolute read-only rule used by historical Phase 0.8 is unchanged.
|
|
Possible future bounded observation would be a separate phase with a new name,
|
|
effect budget, exact permission, and review. This document does not approve
|
|
such a phase.
|
|
|
|
## Immutable historical identity
|
|
|
|
The Phase-0.8 record is anchored to repository commit
|
|
`2c944d6d65a08f7e1c02f518721cde061b999329`.
|
|
|
|
| Immutable file | Role | SHA-256 |
|
|
|---|---|---|
|
|
| `docs/runtime/phase-0.8-read-only-preflight.md` | human-readable historical record | `3fbe086175a6048176075f447ec1482074928e3b5282db97ea2169395fe1d508` |
|
|
| `manifests/runtime/phase-0.8-read-only-preflight.json` | machine-readable historical record | `47d7f452f8799979fe99b3e6d56859f03544112725bf7e5b349eba5ed81b3322` |
|
|
| `tests/test_phase08_preflight.py` | original fail-closed regression | `8a4ad7c70de28ffe3148fd3fd1f68c36a872c53c691c9068e1ff163970863c48` |
|
|
|
|
Historical reporting dated 2026-07-18 recorded 17/17 host tests passing,
|
|
manifest and safety checks passing, and a secret scan passing across 558 text
|
|
files. Those results are historical repository evidence. They are not current
|
|
hardware observations or proof of firmware behavior.
|
|
|
|
The immutable result remains `READ_ONLY_PREFLIGHT_BLOCKED`. Firmware 9.60
|
|
runtime behavior remains `UNPROVEN`. The stock elfldr and Payload Manager
|
|
sizes and hashes remain reference values only; their current on-device
|
|
identity is not established.
|
|
|
|
## Schema boundary
|
|
|
|
The existing artifact schema describes built target artifacts, while the
|
|
controlled-runtime schema describes the separate Phase-0.7 hardened runtime.
|
|
Neither can represent an offline remediation dossier without implying
|
|
inapplicable artifact or deployment semantics. No shared schema is widened.
|
|
The remediation manifest therefore names the dedicated
|
|
`chimera-gfx-phase-0.8-remediation-v1` contract and is validated semantically
|
|
by `tools/validate_phase08_remediation.py`.
|
|
|
|
## Side-effect classification
|
|
|
|
- **A — persistent mutation:** file create/write/delete/rename, configuration
|
|
or autoload change, metadata change, or persistent platform-state change.
|
|
- **B — process- or service-wide mutation:** functional global flags and
|
|
counters, `server_active_flag`, `autoload_triggered`, process/service state,
|
|
signals, or retry state.
|
|
- **C — volatile technical effect:** socket acceptance, temporary buffers,
|
|
allocations, scheduler activity, kernel counters, caches, audit or logging
|
|
paths, and temporary process-local state.
|
|
- **D — observation:** firmware fields, file metadata and hashes, process and
|
|
listener lists, configuration, rollback identities, and storage conditions.
|
|
|
|
No persistent write found is not equivalent to side-effect-free. Category C
|
|
is not claimed absent. Missing observations are unknown, never evidence of
|
|
safe absence.
|
|
|
|
## Pinned Payload Manager source
|
|
|
|
The reviewed local source is public Payload Manager v0.3.1 commit
|
|
`cfbc70f30f419b09bf2b52283f7409e2d3117ee1`. Relevant source identities are
|
|
recorded in `manifests/runtime/phase-0.8-remediation.json`.
|
|
|
|
The three confirmed root findings are:
|
|
|
|
1. `http_on_request()` returns early for `OPTIONS`, then calls
|
|
`log_server_set_active()` for every other request at
|
|
`work/upstream/pldmgr-v0.3.1/src/http_server.c:131-152`.
|
|
`log_server_set_active()` writes the process-global
|
|
`server_active_flag = 1` at
|
|
`work/upstream/pldmgr-v0.3.1/src/log_server.c:20-23`.
|
|
2. `/autoload_status` calls `pldmgr_autoload_get_status()` at
|
|
`work/upstream/pldmgr-v0.3.1/src/http_server.c:847-852`.
|
|
That function writes `autoload_triggered = 1` at
|
|
`work/upstream/pldmgr-v0.3.1/src/autoload.c:44-48`. The worker reads that
|
|
flag when deciding whether to leave its frontend wait and begin the
|
|
countdown at `src/autoload.c:78-93`.
|
|
3. The same handler opens `/data/pldmgr/autoload.txt` and calls
|
|
`config_read()` at `src/http_server.c:854-871`. `config_read()` opens
|
|
`/data/pldmgr/pldmgr_config.txt` at `src/config.c:12-49`.
|
|
|
|
### Request side-effect matrix
|
|
|
|
All handlers below are rooted in `http_on_request()`. “Filesystem/config”
|
|
means project source performs such a read; it does not assert that no other
|
|
read or technical effect occurs.
|
|
|
|
| Method | Endpoint | Handler path | `server_active_flag` | `autoload_triggered` | Filesystem/config | Other proven or unproven effects | Strict read-only |
|
|
|---|---|---|---:|---:|---:|---|---:|
|
|
| `OPTIONS` | `*` | `http_on_request` | no | no | no | response/transport allocations; network, cache, audit, scheduler and kernel effects unproven | **no** |
|
|
| `GET` | `/version` | `http_on_request` | yes | no | no | B: global flag; C: transport effects | **no** |
|
|
| `GET` | `/log` | `http_on_request -> log_build_json` | yes | no | no | B: global flag; C: allocation and mutex; D: ring observation | **no** |
|
|
| `GET` | `/autoload_status` | `http_on_request -> pldmgr_autoload_get_status -> config_read` | yes | yes | yes | B: functional autoload change; C: read/transport effects; D: config observation | **no** |
|
|
| `GET` | `/get_config` | `http_on_request -> config_read` | yes | no | yes | B: global flag; C: atime/audit/cache/metadata unproven; D: config observation | **no** |
|
|
| `GET` | `/list_payloads` | `http_on_request -> payload_mgr_list_json` | yes | no | yes | directory and sidecar scans; possible USB enumeration; technical effects unproven | **no** |
|
|
| `GET` | `/processes_list` | `http_on_request -> process_list_json` | yes | no | no | `sysctl` snapshot and allocation; kernel/audit/scheduler effects unproven | **no** |
|
|
| `GET` | `/sources_list` | `http_on_request -> sources_list_json` | yes | no | yes | not excluded by `is_noisy_route`, so `pldmgr_log()` also writes stdout and the log ring | **no** |
|
|
| `GET` | `/getip` | `http_on_request -> pldmgr_get_local_ip` | yes | no | no | network-interface query; kernel/cache/audit effects unproven | **no** |
|
|
|
|
Supporting locations:
|
|
|
|
- route constants: `include/pldmgr.h:7-44`;
|
|
- noisy-route list and generic request entry:
|
|
`src/http_server.c:108-152`;
|
|
- non-noisy request logging: `src/http_server.c:479-481`;
|
|
- payload and process lists: `src/http_server.c:601-616`;
|
|
- sources list: `src/http_server.c:706-713`;
|
|
- version, log, IP, autoload and config handlers:
|
|
`src/http_server.c:826-954`;
|
|
- ring and stdout mutation: `src/log_server.c:12-55`;
|
|
- payload scan: `src/payload_mgr.c:114-153,196-238`;
|
|
- sources file read: `src/sources.c:28-84,112-134`;
|
|
- process snapshot: `src/process_mgr.c:43-88`.
|
|
|
|
`OPTIONS` is not promoted merely because it returns before the two proven
|
|
flag writes. It provides none of the required device evidence, and network,
|
|
allocation, logging below the reviewed layer, cache, audit, scheduling, and
|
|
kernel-counter effects are still unproven.
|
|
|
|
## Root-cause analysis
|
|
|
|
The current HTTP interface is a frontend-control interface, not an evidence
|
|
collector. A request is treated as evidence that the frontend is active, so
|
|
the server deliberately changes functional process state. The autoload route
|
|
goes further and changes a flag consumed by the autoload worker. This makes
|
|
the interface incompatible with the historical absolute read-only contract
|
|
even where the response body appears informational.
|
|
|
|
A filesystem open using mode `"r"` prevents application-level content writes;
|
|
it does not prove absence of atime, audit records, page-cache activity,
|
|
metadata/cache updates, scheduling, kernel counters, or platform-specific
|
|
effects. Those effects require an exact collector and environment contract.
|
|
|
|
Unavailable data cannot be interpreted as a negative observation. No current
|
|
firmware query, file identity, process/service inventory, listener inventory,
|
|
autoload snapshot, or rollback identity exists in this dossier.
|
|
|
|
A missing Payload Manager backup cannot be created in an absolute read-only
|
|
phase. Creating it necessarily writes a new persistent object and may change
|
|
filesystem allocation and metadata. Backup creation therefore belongs to a
|
|
separate mutating rollback-preparation phase with separate authorization.
|
|
|
|
## Evidence contract for a possible future method
|
|
|
|
No collector is selected. Every timeout below is deliberately unset until the
|
|
collector implementation, transport, and cleanup contract are reviewed. An
|
|
unset timeout, timeout expiry, unknown result, identity drift, or partial
|
|
dataset yields `STOP`.
|
|
|
|
| Observation | Needed fact | Possible source class | Confidence | Known mutations | Unknown effects | Required identity | Timeout | Reviewer return |
|
|
|---|---|---|---|---|---|---|---|---|
|
|
| firmware | two authoritative current values agree exactly | two independently reviewed authoritative sources | `UNPROVEN` | none established | UI/transport/audit/cache/platform query | tool/source/operation identity | unset → `STOP` | raw values, times, identities, agreement |
|
|
| live paths | literal paths, mounts, types, no symlink | reviewed no-follow metadata operation | `UNPROVEN` | none established | atime/audit/cache/namespace | tool, source, no-follow and mount semantics | unset → `STOP` | raw paths, mounts, types, symlink decision |
|
|
| object identities | stable pre/post object/device IDs and full metadata | same reviewed object collector | `UNPROVEN` | none established | cache/audit/race/concurrency | lookup, race, symlink policy | unset → `STOP` | complete pre/post records and errors |
|
|
| file sizes | exact current live byte sizes | same bound object handles | `UNPROVEN` | none established | cache/audit/concurrent modification | same-object and race policy | unset → `STOP` | sizes, references, bindings |
|
|
| SHA-256 | digest of exact current bytes | no-follow same-object streaming hash | `UNPROVEN` | none established | atime/audit/page cache/scheduling | implementation, version, commit, binary hash, open policy | unset → `STOP` | bytes, times, digest, identity, errors |
|
|
| processes/services | all relevant owners, paths, parents, starts and startup modes | reviewed process/service snapshot | `UNPROVEN` | none established | counters/audit/scheduling/locks/cache | tool/API/source/snapshot semantics | unset → `STOP` | raw snapshot and unmapped entries |
|
|
| listeners | owners and binding for 8084/8085/9021 | reviewed listener snapshot | `UNPROVEN` | none established | stack counters/audit/cache/locks/races | tool/API/source/owner mapping | unset → `STOP` | protocol/address/port/owner/exposure |
|
|
| autoload/startup/retry | complete authoritative state; artifacts absent; retry off | collector distinct from stock `/autoload_status` | `UNPROVEN` | stock route mutates `autoload_triggered` | atime/audit/cache/metadata/service/race | tool/source plus complete source list and no-functional-mutation proof | unset → `STOP` | safe raw representations, identities, hashes, decisions |
|
|
| rollback files | separate existing exact backups and restore mappings | same admissible object/hash collector | `UNPROVEN` | none established | atime/audit/cache/metadata/mount/race | hash, object and separation semantics | unset → `STOP` | paths, IDs, hashes, separation and mapping |
|
|
| storage condition | separate target, 2447320 content bytes plus reserve | reviewed capacity/mount operation | `UNPROVEN` | none established | mount/audit/cache/accounting/concurrency | tool/API and capacity semantics | unset → `STOP` | IDs, available bytes, reserve and separation |
|
|
|
|
Any code-bearing collector would additionally require its exact name, version,
|
|
origin, source commit, byte size, SHA-256, complete operation set, imports,
|
|
transitive effects, output channel, cleanup, and fail-closed timeout behavior.
|
|
|
|
## Architecture options — design only
|
|
|
|
| Option | Can prove | Cannot prove | Transfer/execution needed | Persistent effects | Volatile effects | Required permission | Remaining blockers |
|
|
|---|---|---|---|---|---|---|---|
|
|
| A. Current Payload Manager endpoints | limited in-memory version/config/list responses | strict side-effect freedom, complete files/listeners/rollback identity | no new target transfer; requires a network request to an existing process | reads may affect metadata; no content write proven for selected GETs | proven global flags; autoload flag on status; sockets, allocation, logs, caches and audit | new bounded-observation permission would still be required | current interface violates the absolute read-only contract |
|
|
| B. Future one-shot observation method | potentially a purpose-built complete bounded dataset | nothing until source, ABI, transport and cleanup are reviewed | likely transfer and execution, both currently unspecified and unauthorized | must be forbidden by contract but absence is unproven | startup, loader, transport, allocation, scheduling, cache, audit and logs | new exact artifact- and method-bound permission | no design, binary, hash, ABI, timeout or cleanup proof exists |
|
|
| C. Manual/external firmware observation | one user-visible firmware value, possibly an independent second value | live files, processes, listeners, autoload and rollback state | no code transfer or execution if strictly manual | UI/platform persistence is unreviewed | UI, audit, cache and human transcription | new exact observation permission if used as formal evidence | insufficient for the complete preflight |
|
|
| D. Split observation from rollback preparation | observation can be reviewed before any backup write; later backup phase can prove rollback objects | observation alone cannot create missing backups | observation method unknown; backup preparation necessarily performs writes | backup creation, allocation and metadata are expected persistent effects | tool, storage, cache, scheduling and audit effects | separate observation permission, then separate mutating rollback permission | exact live identity and admissible backup procedure remain absent |
|
|
|
|
None of these options is implemented by Phase 0.8R.
|
|
|
|
## Hard gates
|
|
|
|
The active blockers are:
|
|
|
|
1. `exact_permission_quote_absent` — `STOP-RO`;
|
|
2. `collector_identity_absent` — `STOP-RO`;
|
|
3. `collector_side_effect_contract_absent` — `STOP-RO`;
|
|
4. `two_current_firmware_sources_absent` — `STOP-GATE`;
|
|
5. `live_object_identities_absent` — `STOP-GATE`;
|
|
6. `listeners_absent` — `STOP-GATE`;
|
|
7. `autoload_status_absent` — `STOP-GATE`;
|
|
8. `rollback_backups_absent` — `STOP-GATE`;
|
|
9. `payload_manager_backup_not_byte_exact_on_device` — `HARD_STOP-GATE`;
|
|
10. `unknown_result_is_stop` — `STOP`;
|
|
11. `timeout_is_stop` — `STOP`;
|
|
12. `deviation_is_stop` — `STOP`;
|
|
13. `automatic_retry_forbidden` — `STOP`.
|
|
|
|
No general `READY`, `COMPLETE`, or deployment status may override any one of
|
|
these gates. The Payload Manager backup gate can be closed only by
|
|
artifact-specific, current, on-device evidence gathered under a separately
|
|
approved method, not by changing this manifest.
|
|
|
|
## Phase separation
|
|
|
|
Authority never flows forward. Each step requires its own completed review and
|
|
new permission where it involves a target:
|
|
|
|
1. this offline remediation;
|
|
2. a possible later bounded-observation design;
|
|
3. separate permission for any observation transfer or execution;
|
|
4. review of the returned observations;
|
|
5. separate mutating rollback preparation if a backup must be created;
|
|
6. separate installation approval for only hardened elfldr and controlled
|
|
Payload Manager;
|
|
7. installation verification and complete rollback proof;
|
|
8. separate lifecycle approval;
|
|
9. non-graphical capability probes;
|
|
10. much later, a graphics backend and RetroArch.
|
|
|
|
Installation permission does not grant lifecycle permission. Observation
|
|
permission does not grant rollback preparation. No earlier wording may be
|
|
reused for a later artifact, method, or phase.
|
|
|
|
## Relationship to RetroArch
|
|
|
|
RetroArch is a long-term goal, not an active Phase-0.8R workstream. The
|
|
dependency chain is:
|
|
|
|
```text
|
|
offline evidence integrity
|
|
-> admissible bounded observation
|
|
-> verified rollback and installation boundary
|
|
-> separately approved lifecycle
|
|
-> non-graphical capability evidence
|
|
-> later graphics/runtime contracts
|
|
-> later adapters
|
|
-> eventual RetroArch port
|
|
```
|
|
|
|
Phase 0.8R implements none of GNM, VideoOut, SDL, hardware acceleration,
|
|
input, audio, RetroArch frontend behavior, cores, or content launching.
|
|
|
|
## Machine-readable consistency record
|
|
|
|
The validator compares this block structurally with the remediation manifest.
|
|
|
|
<!-- BEGIN PHASE08R_CONTRACT -->
|
|
```json
|
|
{
|
|
"status": "READ_ONLY_PREFLIGHT_BLOCKED",
|
|
"authorization": {
|
|
"authorized": false,
|
|
"installation_authorized": false,
|
|
"lifecycle_authorized": false,
|
|
"execution_authorized": false,
|
|
"transfer_authorized": false,
|
|
"automatic_retry": false
|
|
},
|
|
"blockers": [
|
|
"exact_permission_quote_absent",
|
|
"collector_identity_absent",
|
|
"collector_side_effect_contract_absent",
|
|
"two_current_firmware_sources_absent",
|
|
"live_object_identities_absent",
|
|
"listeners_absent",
|
|
"autoload_status_absent",
|
|
"rollback_backups_absent",
|
|
"payload_manager_backup_not_byte_exact_on_device",
|
|
"unknown_result_is_stop",
|
|
"timeout_is_stop",
|
|
"deviation_is_stop",
|
|
"automatic_retry_forbidden"
|
|
],
|
|
"firmware_runtime_behavior": "UNPROVEN",
|
|
"stock_identity_classification": "reference_only",
|
|
"payload_manager_backup_classification": "hard_blocker",
|
|
"retroarch_active_phase": false
|
|
}
|
|
```
|
|
<!-- END PHASE08R_CONTRACT -->
|