@modelprofile.com/browser-runtime 4.3.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +34 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.runtime.d.ts +43 -11
- package/dist_ts/classes.runtime.js +574 -570
- package/dist_ts/classes.runtimeownership.d.ts +3 -1
- package/dist_ts/classes.runtimeownership.js +27 -7
- package/dist_ts/index.d.ts +2 -2
- package/dist_ts/interfaces.d.ts +8 -3
- package/dist_ts/mcp.js +5 -3
- package/package.json +2 -2
- package/readme.hints.md +13 -10
- package/readme.md +22 -8
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.runtime.ts +620 -638
- package/ts/classes.runtimeownership.ts +23 -6
- package/ts/index.ts +5 -1
- package/ts/interfaces.ts +9 -3
- package/ts/mcp.ts +5 -2
package/readme.hints.md
CHANGED
|
@@ -8,11 +8,12 @@ Durable implementation findings for `@modelprofile.com/browser-runtime`.
|
|
|
8
8
|
- Persistent, fsynced `runtime.lock` metadata is a downgrade fence, not the live mutex, and is never removed by normal shutdown. Every start owns one metadata-named generation containing private profile and artifact roots.
|
|
9
9
|
- Metadata-generation recovery performs no lock-descriptor scan. It removes only the exact named generation after checking every same-UID process for an absolute `--user-data-dir` equal to or below that profile root; this check is process-generic, not Chromium-specific.
|
|
10
10
|
- Process ownership comes from all four `/proc/<pid>/status` `Uid:` values, not `/proc/<pid>` directory ownership. Only an exact same-UID or definite other-UID classification is actionable; mixed, unreadable, malformed, symlinked, wrongly owned/mode, hard-linked, ambiguous, or uncontained ownership state remains fenced.
|
|
11
|
+
- An empty process command line triggers one status revalidation. A conclusively departed PID (both status and PID directory missing), definite other UID, or exact same-UID zombie is clear. A still-present PID with missing/unreadable status, ambiguous UID, or malformed/duplicate state remains fenced; exit between command-line and status reads does not block startup.
|
|
11
12
|
- Legacy zero-byte locks alone use SmartIPC's consuming kernel probe for other read/write open descriptions. Adoption additionally requires birth, change, and modification timestamps strictly before bounded `/proc/stat` `btime`, plus no same-UID process using the exact or descendant legacy profile root. After an exclusive probe, Runtime reopens and revalidates the exact original inode, ownership, mode, link count, zero size, and timestamps. Probe contention is locked; probe or reopen uncertainty, same-boot, malformed, or ambiguous state remains fenced against the 3.2 close-before-unlink race. `O_PATH` descriptors do not contend.
|
|
12
13
|
- A clean 3.2 stopped layout has no lock and may retain private empty top-level profile and artifact roots. The native-mutex winner validates, process-checks, and removes only those roots. Before metadata fsync succeeds, failure cleanup may unlink only the exact lock inode that acquisition just created; preexisting locks are never removed.
|
|
13
14
|
- Shutdown attempts artifact and ownership cleanup after peer, revocation, or resource failures, retains retryable local slot state, and blocks restart until that state clears. Automatic ownership-loss cleanup gets one bounded retry; stale active metadata remains a fail-closed recovery fence.
|
|
14
15
|
- Controller durable truth is a logical resource with immutable `projectId`, stable random `browserResourceId`, and a revisioned attachment binding. Runtime state is process-local and must be re-registered after every restart.
|
|
15
|
-
- A resource slot owns
|
|
16
|
+
- A resource slot owns its browser incarnation, transition mutex, generations, exact participant leases, shared bounded FIFO, independent viewer frame windows, authenticated egress proxy, private profile, and idle timer. Joining or releasing a participant does not change the resource arbitration generation.
|
|
16
17
|
- `terminateResource()` and idle termination remove only the incarnation. They preserve registration, attachment, capabilities, and artifacts. `retireResource()` permanently fences, revokes, terminates, purges exact-resource artifacts, then unregisters only after all cleanup succeeds. Durable retirement remains Controller truth; Runtime tombstones are bounded and process-local.
|
|
17
18
|
- Failed retirement retains a fenced, retryable registration. Unknown profile, lock, or artifact ownership remains fail closed.
|
|
18
19
|
- Launch quota admission uses synchronous pending reservations across global and per-project running-resource limits.
|
|
@@ -20,15 +21,17 @@ Durable implementation findings for `@modelprofile.com/browser-runtime`.
|
|
|
20
21
|
## Attachment and capability boundary
|
|
21
22
|
|
|
22
23
|
- Attachment revision is independent from incarnation and arbitration generations. Equal revisions are idempotent only for an identical binding; lower or conflicting equal revisions fail.
|
|
23
|
-
- Any `sessionId: null` binding is detached; revision zero is
|
|
24
|
-
- Agent capabilities require the exact current
|
|
24
|
+
- Any `sessionId: null` binding is detached; revision zero is the initial detached/no-agent-authority state. Attachment transitions fence and revoke only agent authority. Human viewers keep resource access. An agent operation that cannot quiesce still requires terminating that resource's incarnation.
|
|
25
|
+
- Agent capabilities require the exact current qualified session. Human issuance validates the attachment current at issuance, but subsequent human operations authorize the exact project/resource/actor/peer independently from agent attachment changes. Flex run channels use trusted pipes; independently authenticated MCP bindings support OpenCode, Codex, and Flex session IDs without impersonating a Flex run channel.
|
|
25
26
|
- Capability tokens are returned once. Runtime records retain only SHA-256 digests and use `timingSafeEqual`. Authorization is rechecked after asynchronous host authorization, during lease acquisition, and before and after every operation.
|
|
26
27
|
- Capability, audit, and lease identity includes immutable project, resource, attachment authority and revision, actor, peer, role, source, qualified agent session, and Flex scope/channel/run where applicable.
|
|
27
|
-
-
|
|
28
|
-
- Human frame refresh
|
|
28
|
+
- All participant operations share a resource FIFO with per-lease and aggregate bounds. A released participant's cleanup joins that same FIFO with exact retained lease identity, bypasses user-operation authorization only for resource-owned input release/viewport recomputation, and retains lifecycle cancellation and operation timeout enforcement.
|
|
29
|
+
- Human frame refresh enters the shared FIFO, captures the initiating subscription, clears viewer windows, waits for producer acknowledgements, and validates one constant-sized new-generation boundary. A running open tab may refresh while streaming is false. New frames fan out to all participants.
|
|
29
30
|
- `beforeOperation` reserves the exact resource and lets the host persist policy/audit through an awaited fail-closed gate. Runtime then atomically revalidates lease, attachment, session, arbitration generation, and incarnation before starting the side effect. Both host hooks carry the same exact operation ID and classification; terminal audit remains best effort and runs after bounded cleanup releases or fences the exact reservation.
|
|
30
31
|
- Lease authority snapshots are immutable process-local revalidation tokens. They expose `authorityGeneration` and bind the runtime instance, incarnation, exact `capabilityId`, exact `leaseId`, and attachment, but never replace Controller durable attachment truth.
|
|
31
32
|
|
|
33
|
+
- Viewport preferences are per human lease. Effective width, height and DSF use the componentwise minimum; results carry the actual viewport revision, including unchanged-size responses. Departure expands the viewport through serialized resource-owned cleanup and retains its cleanup marker until the resize succeeds, so failed cleanup remains retryable. Input ownership is bounded to 64 keys and 5 buttons per participant, and departure preserves another participant's held input.
|
|
34
|
+
|
|
32
35
|
## Browser confinement
|
|
33
36
|
|
|
34
37
|
- Production session options are assembled only inside `BrowserRuntime`: sandbox required, random private per-resource user data directory, one authenticated proxy per running resource, fixed network-reduction arguments, denied downloads/file choosers/permissions, and HTTP(S)-only public navigation.
|
|
@@ -47,11 +50,11 @@ Durable implementation findings for `@modelprofile.com/browser-runtime`.
|
|
|
47
50
|
- Framed messages contain no identity selectors. The parent binds project, resource, attachment authority/revision, actor, peer, role, source, qualified session, Flex scope, channel, and exact run out of band.
|
|
48
51
|
- One qualified session can own multiple resource-specific framed channels. Capability revocation owns server-peer disconnect; peer-initiated release/close revokes only that channel's capability without recursively disconnecting itself.
|
|
49
52
|
- Framed request counts and queued write bytes are bounded. Runtime shutdown has a bounded caller-visible cleanup deadline while retaining in-flight cleanup ownership for retry.
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
- A frame above `maxFrameBytes`
|
|
53
|
+
- Each viewer has a bounded exact-identity frame map. Each incoming frame starts one bounded producer ACK whose outcome is shared by viewer records. Producer ACK promises have a separate hard bound; viewer lag and eviction cannot re-ACK or block Chrome. Producer failures fence the exact incarnation regardless of which participants subsequently joined it. A failure from an older incarnation cannot fence its replacement.
|
|
54
|
+
- Late viewer acknowledgements and oldest-first eviction only retire the local map entry. A throwing listener revokes its own participant. Neither event routes through resource-wide producer failure handling.
|
|
55
|
+
- A frame above `maxFrameBytes` advances the resource sequence watermark, is acknowledged once and dropped, and reports nonfatal `FRAME_TOO_LARGE` to viewers. During refresh it also fails the refresh boundary with `FRAME_TOO_LARGE`.
|
|
53
56
|
- `screencast` (`quality` 0..100 default 70, `maxWidth`/`maxHeight` 1..4096 each with `maxWidth * maxHeight <= 8_294_400` and defaults 2560/1600, `everyNthFrame` 1..60 default 1, `firstFrameTimeoutMs` 1000..60000 default left to SmartPuppeteer) is validated in the constructor with `validateExactKeys` plus the integer validators and forwarded to `LiveBrowserSession` next to `maxOutstandingFrames`. The ceilings deliberately match `@push.rocks/smartpuppeteer` 2.6's `LiveBrowserSession` validation (`maxViewportPixelArea = 8294400`, `maxTimeoutMs = 60000`); a looser runtime bound would let `new BrowserRuntime()` succeed and every incarnation launch fail instead. Without `quality`/`maxWidth`/`maxHeight`, SmartPuppeteer's defaults (quality 80, unbounded size) produced multi-megabyte frames on device-pixel-ratio 2 viewers.
|
|
54
|
-
-
|
|
55
|
-
- Runtime state
|
|
57
|
+
- Refresh records track bounded producer ACK work independently of viewer windows. Producer failure cleanup is coalesced by exact session; affected operation completion waits for the fence and process cleanup. Closing an initiating subscription abandons its refresh without revoking other viewers.
|
|
58
|
+
- Runtime state/error messages are bounded to 2,048 characters. Fatal producer errors revoke every current participant synchronously before captured error delivery; released participants receive no duplicate fatal notification.
|
|
56
59
|
- Flex resolves only a capability token, and the provider's run must exactly match its trusted framed client. SmartAgent exposes exactly navigate, snapshot, screenshot, click, fill, and press.
|
|
57
60
|
- MCP independent authentication returns the complete expected binding. The binding is retained in server-owned auth context and tool schemas expose no resource, session, revision, or authority selector.
|
package/readme.md
CHANGED
|
@@ -72,7 +72,7 @@ try {
|
|
|
72
72
|
}
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
Projects and qualified OpenCode, Flex, and Codex sessions may each own many resources.
|
|
75
|
+
Projects and qualified OpenCode, Flex, and Codex sessions may each own many resources. Agent capabilities use Flex's trusted pipe or an independently authenticated MCP binding for any supported native session. Each resource has one browser incarnation and operation queue shared by its attached agent and multiple human viewers. Joining a viewer never preempts another participant.
|
|
76
76
|
|
|
77
77
|
`registerResource()` is idempotent only for the same project/resource key and identical attachment. `listResources()` reports process-local registration and incarnation metadata. `terminateResource()` terminates only the current incarnation and preserves registration, attachment, and artifacts. `retireResource()` permanently fences the process-local registration, revokes and quiesces authority, terminates its incarnation, purges exact-resource artifacts, and unregisters only after cleanup succeeds. The Controller separately owns durable retirement truth and must not rehydrate retired resources. Runtime tombstones and registrations are ephemeral, bounded process state. `stop()` attempts peer, capability, resource, artifact-store, and ownership cleanup even when an earlier stage fails, then reports all failures together. It removes only the current generation, durably marks its owner metadata relinquished, and releases the native ownership lease when ownership cleanup succeeds. It intentionally leaves `runtime.lock` and the mutex anchor in place. Failed local slot cleanup remains retryable and blocks a new generation; automatic ownership-loss shutdown performs one additional bounded cleanup attempt. `cleanupTimeoutMs` defaults to 30,000 milliseconds and accepts values from 100 through 120,000. If that caller-visible deadline expires, `stop()` rejects with `TIMEOUT` while Runtime retains cleanup still in flight; a later `stop()` rejoins it, and `start()` waits for all prior local cleanup before restarting.
|
|
78
78
|
|
|
@@ -90,6 +90,8 @@ When version 3.2 stopped cleanly and removed `runtime.lock`, it may leave empty
|
|
|
90
90
|
|
|
91
91
|
## Breaking Changes
|
|
92
92
|
|
|
93
|
+
Shared control replaces exclusive human takeover. Hosts must allow multiple exact participant leases, stop treating chat attachment changes as human-view revocation, and consume the effective viewport returned by `setViewport()`. Browser destruction remains an explicit resource operation.
|
|
94
|
+
|
|
93
95
|
The version 3.2 runtime-directory migration is one-way. A cleanly stopped 3.2 runtime that removed its zero-byte lock can be upgraded directly when any remaining top-level `profiles` and `artifacts` directories are private and empty. A stale 3.2 lock is recoverable only after reboot, once it conclusively predates the current boot and no legacy holder or profile process remains. The first successful new-runtime start writes permanent metadata and creates `runtime.mutex`; version 3.2 must not reuse that directory.
|
|
94
96
|
|
|
95
97
|
To downgrade, first stop the new runtime and verify that no process still uses any generation profile path. Then remove the entire runtime directory, including `runtime.lock`, `runtime.mutex`, and `generations`, and let version 3.2 create a fresh directory. Never delete only the lock or anchor, and never perform this procedure while either runtime generation is active.
|
|
@@ -110,29 +112,41 @@ await runtime.applyAttachmentBinding({
|
|
|
110
112
|
});
|
|
111
113
|
```
|
|
112
114
|
|
|
113
|
-
A newer binding
|
|
115
|
+
A newer binding fences agent admission, revokes older agent capabilities, and quiesces their active work. Human viewers retain their resource authority and subscriptions. The incarnation is preserved unless an operation cannot quiesce; that failure requires terminating the resource's browser process.
|
|
116
|
+
|
|
117
|
+
Agent capabilities require the exact current non-detached qualified session. Human capabilities carry no session ID and may be issued while detached. Issuance validates the current attachment binding, but an issued human capability remains valid across attachment changes: hosts must authorize it against its project, resource, actor and peer rather than the resource's later agent assignment.
|
|
114
118
|
|
|
115
|
-
|
|
119
|
+
Capabilities expire after five minutes by default. A host keeping a viewer open can call
|
|
120
|
+
`await lease.renew({ signal })` before `lease.expiresAt`; the result is the new expiry
|
|
121
|
+
time in Unix milliseconds. Renewal invokes `authorizeCapability` again and preserves
|
|
122
|
+
the exact lease, browser incarnation, frame subscription and attachment identity.
|
|
123
|
+
`expiresInMs` optionally selects a lifetime within the configured maximum. An expired,
|
|
124
|
+
released, revoked or replaced lease cannot be renewed. A denied, cancelled or timed-out
|
|
125
|
+
renewal leaves the original expiry unchanged. Only one authorization callback per lease
|
|
126
|
+
may remain unsettled, including after timeout; runtime-wide renewal admission is bounded
|
|
127
|
+
by `maxCapabilities`. Hosts must stop scheduling renewal when their viewer disconnects.
|
|
116
128
|
|
|
117
129
|
Agent actions are exactly `navigate`, `snapshot`, `screenshot`, `click`, `fill`, and `press`. Human leases additionally expose tab lifecycle, viewport, raw input, frame subscription/acknowledgement and refresh, and exact-resource artifact reads/deletes. JavaScript evaluation is not public.
|
|
118
130
|
|
|
119
|
-
|
|
131
|
+
All participants enter one strict resource FIFO. `maxQueuedOperationsPerLease` defaults to 128 and accepts 1 through 1,024; each participant has that bound, and the resource queue is bounded by its product with `maxCapabilitiesPerResource`. Overflow fails with `QUOTA_EXCEEDED`. Releasing a participant cancels only its queued and active work. Resource termination and shutdown cancel everyone. Started uncertain work must quiesce or the exact incarnation is terminated before operation settlement.
|
|
132
|
+
|
|
133
|
+
`setViewport()` stores the viewer's preferred width, height and device scale factor and returns `IBrowserRuntimeViewportResult` with the effective `viewport` and `viewportRevision`. The effective values are the componentwise minima across active viewers that have supplied a preference. Unchanged effective sizes do not restart the stream. Removing a viewer recomputes the viewport in the resource FIFO. Held keys and buttons are tracked per participant; leaving releases only inputs that no other participant holds. Viewport and tab/navigation transitions clear held input before changing the target. Resource-owned departure cleanup is bounded and audited as `releaseParticipant`; it does not call the external `beforeOperation` gate after the participant has lost access.
|
|
120
134
|
|
|
121
135
|
`beforeOperation` is an optional awaited fail-closed gate. It receives the complete immutable authority, operation/capability/lease IDs, action, classification, start time, and an `AbortSignal` after dequeue but before the browser side effect starts. Classifications are `raw-input`, `frame-stream`, `viewport`, `navigation`, `tab`, and `agent-action`. Hosts that require durable attempt-before-side-effect auditing should persist the attempt there. Rejection denies the operation. The default `beforeOperationTimeoutMs` is 10,000 milliseconds and accepts values from 100 through 120,000; timeout fails with `TIMEOUT`. The terminal `audit` callback remains a best-effort `completed`/`failed` notification correlated by the same operation ID and classification and runs after bounded operation cleanup releases or fences the exact reservation.
|
|
122
136
|
|
|
123
137
|
`lease.getAuthority()` returns an immutable process-local lease authority containing the runtime authority ID, exported `authorityGeneration`, incarnation generation, and complete capability binding. Every snapshot also binds the exact `capabilityId` and `leaseId`. `lease.isAuthorityCurrent(authority)` performs an exact synchronous revalidation suitable for a host-owned virtual stream. These values are not durable Controller state and do not replace attachment checks against the Controller database.
|
|
124
138
|
|
|
125
|
-
|
|
139
|
+
Each human participant may have one independent frame subscription with a bounded exact-identity window. `maxOutstandingFrames` defaults to 4 and accepts 1 through 32. Runtime starts exactly one bounded producer acknowledgement per admitted frame and shares its outcome between subscribers. Viewer acknowledgements and oldest-first eviction retire only that viewer's entry; they never acknowledge the producer a second time. A producer result of `accepted: false` is a settled result, while rejection, timeout or producer admission overflow fences the failed incarnation. A throwing viewer listener revokes only that participant.
|
|
126
140
|
|
|
127
|
-
|
|
141
|
+
`frameAcknowledgementTimeoutMs` defaults to 10,000 milliseconds and accepts 100 through 60,000. It bounds producer acknowledgements and each viewer's local window lifetime independently. A late viewer acknowledgement returns `false` once its entry has expired; it does not stop the browser, revoke another participant, or delay producer delivery.
|
|
128
142
|
|
|
129
143
|
An oversized frame is dropped, not fatal. `maxFrameBytes` defaults to 4 MiB and accepts values from 64 KiB through 16 MiB. A frame above the bound is acknowledged toward SmartPuppeteer in the background, never enters the application window, and is reported once on the subscription as `{ type: 'error', error: { code: 'FRAME_TOO_LARGE', fatal: false, tabId } }`. The sequence watermark advances past the dropped frame so later frames remain valid and continue to be delivered.
|
|
130
144
|
|
|
131
145
|
`screencast` tunes the Chromium screencast that SmartPuppeteer starts for every incarnation. `quality` is the JPEG quality from 0 through 100 and defaults to 70. `maxWidth` and `maxHeight` accept values from 1 through 4,096 each, their product must not exceed 8,294,400 pixels (SmartPuppeteer's ceiling, so 3,840×2,160 is accepted and 4,096×4,096 is rejected with `INVALID_INPUT`), they default to 2,560 and 1,600, and they make Chromium scale captured frames to fit. `everyNthFrame` accepts values from 1 through 60 and defaults to 1. `firstFrameTimeoutMs` accepts values from 1,000 through 60,000 and is left to SmartPuppeteer's default when omitted. Runtime forwards these values together with `maxOutstandingFrames`; the defaults keep frames from device-pixel-ratio 2 viewers well below `maxFrameBytes`.
|
|
132
146
|
|
|
133
|
-
Human state and error events retain an optional diagnostic `message` bounded to 2,048 characters. A fatal
|
|
147
|
+
Human state and error events retain an optional diagnostic `message` bounded to 2,048 characters. A fatal producer error synchronously invalidates all current participants before their captured subscribers receive the error. Cleanup is coalesced for that exact incarnation and completes before affected operations settle.
|
|
134
148
|
|
|
135
|
-
`humanLease.refreshFrameStream(options?: IBrowserRuntimeOperationOptions): Promise<void>` requires
|
|
149
|
+
`humanLease.refreshFrameStream(options?: IBrowserRuntimeOperationOptions): Promise<void>` requires that participant's current subscription and enters the shared audited FIFO. It works for a running, open active tab even when its stream is invalidated. Runtime clears old viewer windows, waits for producer acknowledgement work, and validates the returned new-generation boundary against the current tab, viewport, session and incarnation. Every viewer receives the new stream. Missing or replaced subscriptions fail with `BUSY`; an abandoned initiator returns `ABORTED` without removing other viewers. A broken producer or invalid refresh boundary fails with `FRAME_STREAM_FAILED` or `FRAME_TOO_LARGE` after exact-incarnation cleanup. Caller cancellation preserves a successfully restored stream.
|
|
136
150
|
|
|
137
151
|
## Trusted Pipe And Flex
|
|
138
152
|
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@modelprofile.com/browser-runtime',
|
|
6
|
-
version: '
|
|
6
|
+
version: '5.0.0',
|
|
7
7
|
description: 'Parent-owned, resource-centric Chromium runtime with revisioned attachment fencing, authenticated human and agent control, fail-closed egress, bounded artifacts, and Flex/MCP adapters.'
|
|
8
8
|
}
|