|
| 1 | +# Helper Causal Receipts v0.1 |
| 2 | + |
| 3 | +Status: Draft |
| 4 | +Scope: SourceOS Shell, BearBrowser, TurtleTerm, Office/PDF runtime, preview/rendering helpers |
| 5 | +Primary goal: preserve user-legible causal intent across helper-process boundaries. |
| 6 | + |
| 7 | +## Problem |
| 8 | + |
| 9 | +- Modern desktop actions are not single-process events. |
| 10 | +- A visible action such as previewing a file, opening a native file picker, rendering a thumbnail, taking a screenshot, cleaning browser cache, or indexing metadata can spawn a hidden helper-process cascade. |
| 11 | +- The macOS unified-log sample that motivated this spec shows repeated helper lifecycle patterns: demand spawn, `xpcproxy` materialization, source attachment, running/init transitions, sandbox-denied lookups, clean exits, supervisor kills, and teardown races. |
| 12 | +- The useful primitive is not the raw process log. The useful primitive is a root-intent-bound receipt. |
| 13 | +- SourceOS must not repeat the opaque pattern where users see helper churn but cannot answer: why did this run, what requested it, what data did it touch, what was denied, and did network/clipboard/account/analytics access occur? |
| 14 | + |
| 15 | +## Design Principles |
| 16 | + |
| 17 | +- Every helper process carries a `root_intent_id`. |
| 18 | +- Every helper spawn has a declared purpose. |
| 19 | +- Every sensitive capability request is recorded as a policy decision. |
| 20 | +- Every denied capability records whether data was accessed. For a sandbox denial, the default is `data_accessed=false` unless an allow event proves otherwise. |
| 21 | +- Every helper exit records completion, duration, and receipt completeness. |
| 22 | +- Every teardown race is normalized before user presentation. |
| 23 | +- Expected denials are evidence of containment, not automatic alerts. |
| 24 | +- Unexpected denials are policy-regression candidates. |
| 25 | +- Local preview helpers deny network, DNS, pasteboard, account lookup, analytics, camera, microphone, location, credential stores, and arbitrary file reads by default. |
| 26 | +- Web thumbnailing is treated as hostile-content rendering, not as static image generation. |
| 27 | +- Native file picker helpers must not inherit browser session authority. |
| 28 | +- Terminal preview helpers must not inherit shell secrets. |
| 29 | + |
| 30 | +## Event Types |
| 31 | + |
| 32 | +| Event Type | Purpose | Required Fields | |
| 33 | +|---|---|---| |
| 34 | +| `root_intent.created` | Start a causal graph for a visible or scheduled action | `event_id`, `root_intent_id`, `timestamp`, `surface`, `actor`, `declared_purpose`, `data_scope`, `default_policy`, `receipt_required` | |
| 35 | +| `helper.spawn` | Record subprocess/helper launch | `event_id`, `parent_event_id`, `root_intent_id`, `parent_process`, `child_process`, `trigger`, `spawn_reason`, `policy_profile` | |
| 36 | +| `capability.request` | Record sensitive service/capability lookup | `event_id`, `root_intent_id`, `requestor`, `capability`, `requested_service`, `decision`, `classification`, `policy_rule`, `data_accessed` | |
| 37 | +| `helper.exit` | Record termination and cleanup | `event_id`, `root_intent_id`, `process`, `exit_status`, `duration_ms`, `children_cleaned`, `unexpected_denials`, `network_used`, `receipt_complete` | |
| 38 | +| `teardown.normalized` | Normalize noisy cleanup/race messages | `raw_message`, `normalized_class`, `severity`, `meaning`, `receipt_complete`, `policy_impact` | |
| 39 | +| `policy.decision` | Record policy evaluation | `policy_profile`, `rule_id`, `capability`, `decision`, `reason`, `override_actor`, `override_expiry` | |
| 40 | +| `data.touch` | Record data class touched | `object_type`, `object_hash`, `path_policy`, `access_mode`, `retention`, `derived_artifact` | |
| 41 | + |
| 42 | +## Policy Profiles |
| 43 | + |
| 44 | +### `preview.local_only.v1` |
| 45 | + |
| 46 | +- Applies to local PDF, image, office, and generic file previews. |
| 47 | +- Allows selected file snapshot reads, thumbnail cache writes, CPU rendering, mediated GPU rendering, allowlisted system font reads, and IPC to the preview broker. |
| 48 | +- Denies network, DNS, pasteboard, analytics, account lookup, contacts, calendar, camera, microphone, location, arbitrary file reads, and unrestricted child processes. |
| 49 | + |
| 50 | +### `preview.web_thumbnail.local_only.v1` |
| 51 | + |
| 52 | +- Applies to HTML thumbnails, web archive previews, local browser export previews, and URL snapshot rendering. |
| 53 | +- Risk model: hostile-content rendering. |
| 54 | +- Allows parsing and rendering the selected local snapshot plus mediated GPU rendering and local thumbnail output. |
| 55 | +- Denies network, DNS, cookies, credentials, local/session storage, extension APIs, service workers, remote fonts, pasteboard, account lookup, analytics, camera, microphone, and location. |
| 56 | +- Non-negotiable invariant: web thumbnail helpers never inherit browser session authority. |
| 57 | + |
| 58 | +### `cache_cleanup.local_only.v1` |
| 59 | + |
| 60 | +- Applies to browser/app cache cleanup and local cache size accounting. |
| 61 | +- Allows cache metadata read, cache entry delete, cache size compute, and local policy report. |
| 62 | +- Denies network, DNS, analytics, account lookup, remote sync, and browser session reads. |
| 63 | +- Special rule: if a network-shaped helper is spawned, its receipt must state whether network authority was actually granted or whether only local cache metadata was inspected. |
| 64 | + |
| 65 | +### `file_picker.native_ui.v1` |
| 66 | + |
| 67 | +- Applies to native open/save panels and file picker preview surfaces. |
| 68 | +- Allows selected file grants, UI rendering, and preview-broker IPC. |
| 69 | +- Denies account lookup, cloud sync triggers, pasteboard access, analytics, browser extension invocation, cookie reads, and browser session reads. |
| 70 | +- Special rule: native file picker helpers must not inherit browser session authority. |
| 71 | + |
| 72 | +### `terminal.preview.local_only.v1` |
| 73 | + |
| 74 | +- Applies to TurtleTerm file previews, hyperlink previews, archive listings, and command-output renderers. |
| 75 | +- Allows selected file/path preview, local rendering, and local temporary artifacts. |
| 76 | +- Denies shell environment reads, shell history reads, SSH key reads, token reads, network fetches, clipboard reads, account lookup, and analytics. |
| 77 | +- Special rule: terminal preview helpers must never inherit shell secrets. |
| 78 | + |
| 79 | +## Denial Classification |
| 80 | + |
| 81 | +| Classification | Meaning | Default Severity | |
| 82 | +|---|---|---| |
| 83 | +| `expected_denial` | Policy intentionally blocked a commonly probed service | notice | |
| 84 | +| `unexpected_denial` | Helper requested capability outside declared profile | warning | |
| 85 | +| `compatibility_probe` | Framework probed optional service and did not require it | notice | |
| 86 | +| `policy_regression` | New build began requesting undeclared capability | error in CI | |
| 87 | +| `malicious_probe_candidate` | Request unrelated to purpose and targeting sensitive data | critical | |
| 88 | +| `missing_service` | Target service absent or not running | notice | |
| 89 | +| `teardown_race` | Request/reply path raced with helper shutdown | trace/notice | |
| 90 | + |
| 91 | +## Teardown Normalization |
| 92 | + |
| 93 | +| Raw Pattern | Normalized Class | Meaning | |
| 94 | +|---|---|---| |
| 95 | +| `no client port found` | `client_endpoint_missing_after_teardown` | Client disappeared before service reply completed | |
| 96 | +| `invalid client reply port -1` | `invalid_reply_endpoint_after_teardown` | Reply endpoint invalid during cleanup | |
| 97 | +| `job not found` / `ENOSERVICE` | `service_removed_before_reply` | Service exited before late lookup/reply completed | |
| 98 | +| `Operation already in progress` | `duplicate_activation_coalesced` | Duplicate demand while helper already running | |
| 99 | +| supervisor `SIGKILL` | `supervisor_worker_lifecycle_kill` | Supervisor ended bounded worker | |
| 100 | + |
| 101 | +## User Inspector Requirements |
| 102 | + |
| 103 | +- Provide a local “Why did this run?” view. |
| 104 | +- Group by `root_intent_id`, not raw PID. |
| 105 | +- Show visible action, parent surface, helper chain, allowed capabilities, denied capabilities, data touched, network/DNS outcome, exit status, incomplete receipts, and policy regressions. |
| 106 | +- Expected denials should be visible on expansion, but not noisy by default. |
| 107 | +- Policy regressions and incomplete receipts should be surfaced immediately. |
| 108 | + |
| 109 | +## Acceptance Tests |
| 110 | + |
| 111 | +| Test | Given | Assert | |
| 112 | +|---|---|---| |
| 113 | +| Root intent propagation | Any helper spawn | `root_intent_id`, `parent_event_id`, `spawn_reason`, and `policy_profile` exist | |
| 114 | +| Local preview no-network | Local PDF/image preview | network, DNS, analytics, and account lookup denied | |
| 115 | +| Web thumbnail isolation | HTML/web thumbnail render | cookies, storage, extensions, network, and pasteboard denied | |
| 116 | +| Cache cleanup transparency | Cache cleanup spawns network-shaped helper | receipt explains reason and egress decision | |
| 117 | +| Native file picker isolation | Browser invokes native file panel | no browser session or extension authority inherited | |
| 118 | +| Terminal preview isolation | TurtleTerm preview | shell secrets and environment denied | |
| 119 | +| Receipt completeness | Completed action | all helper spawns have exit or active-state events | |
| 120 | +| Denial classification | Denied capability request | denial classified and `data_accessed` recorded | |
| 121 | +| Policy regression CI | New undeclared capability | CI fails unless policy is updated | |
| 122 | +| Inspector rendering | Completed DAG | user-readable summary exists | |
| 123 | + |
| 124 | +## Repo Integration |
| 125 | + |
| 126 | +| Repo | Role | |
| 127 | +|---|---| |
| 128 | +| `SourceOS-Linux/sourceos-shell` | Runtime receipt store, helper wrapper, parser/correlator, local inspector | |
| 129 | +| `SourceOS-Linux/BearBrowser` | Browser file picker, cache cleanup, preview and thumbnail helper enforcement | |
| 130 | +| `SourceOS-Linux/TurtleTerm` | Terminal preview and command helper secret isolation | |
| 131 | +| `SocioProphet/ontogenesis` | Ontology classes, properties, SHACL constraints | |
| 132 | +| `SocioProphet/prophet-platform` | Evidence-envelope mapping, evidence-console view, CI trust gates | |
| 133 | + |
| 134 | +## Non-Goals |
| 135 | + |
| 136 | +- Do not alert for every expected denial. |
| 137 | +- Do not ban short-lived helpers. |
| 138 | +- Do not ban multiprocess rendering. |
| 139 | +- Do not assume every denial is malicious. |
| 140 | +- Do require causality, classification, policy, and receipts. |
| 141 | + |
| 142 | +## Security Invariants |
| 143 | + |
| 144 | +- Preview helpers are local-only by default. |
| 145 | +- Web thumbnails do not inherit browser session state. |
| 146 | +- Cache cleanup does not receive network authority by default. |
| 147 | +- Native file picker helpers do not inherit browser extension authority. |
| 148 | +- Terminal preview helpers do not inherit shell secrets. |
| 149 | +- Every sensitive capability decision is recorded. |
| 150 | +- Every helper exit is recorded. |
| 151 | +- Incomplete receipts degrade trust state. |
0 commit comments