Dashboard › opencode › Session 0GocXtkoF6Rp
0GocXtkoF6RpKz0b5Perform a final substantive independent READ-ONLY security review of the exact current source and artifacts under /home/byk/.local/share/opencode-v2-pilot/supervisor, plugin files /home/byk/.local/share/opencode-v2-pilot/config/opencode/plugins/pty.ts and pty-transport.ts, canonical config tsconfig/package files, candidate unit, CUTOVER, and persistent/temp PTY tests. Immutable claimed source manifest: fff146df36754bc59d473a070985c4310cb57bdad64473ec7f68b5be5014286f. Claimed artifact hashes: supervisor ff03df72fc6a401e8070db776ceba524e9111d9d907c6f4939244354564a86f2; launcher d833c859476f021565e8f425e6ee51353909060fa5f64ce629fb07d3411987dd; client fb8739d98ff7882782005e04ef731b6120e8daf0719e606362a1fe620adc2cde. Verify every prior security blocker: Service ControlGroup; forge-proof cleanup using independent bounded state proof and safe signal handling; bounded STOP; bounded pre-listener output; no fd leak on MSG_CTRUNC; same-UID deployment blocker truth and marker gate; flood cannot deny real MainPID; exact marker paths/order/source binding; canonical tsgo; helper runtime-open wording; Node 26 gate. Reassess full threat model: same-UID ptrace/fd delegation, PID reuse, cgroups, cwd, protocol/parser, D-Bus sender/signals, systemd properties, root attack surface, supplementary groups, external sockets, resources, orphan units, malicious output/input. Inspect all changed files and tests, verify manifest/hashes and reproducible builds. Run unprivileged checks if useful. Never edit/install/start/stop services or perform privileged actions. Distinguish source approval from root-host deployment acceptance. Cite current file:line evidence, classify PASS/CONCERN/MUST-FIX, and end exactly MERGE or DO-NOT-MERGE.
I will freeze the review scope by hashing the claimed tree and artifacts first, then trace each blocker through source, tests, unit/config, and cutover documentation. I will keep all checks unprivileged and build only into /tmp/opencode; I will not change files or service state.
[
{
"content": "Inventory and hash exact supervisor, plugin, config, unit, CUTOVER, and PTY test scope",
"status": "in_progress",
"priority": "high"
},
{
"content": "Trace every prior blocker and the full threat model through current source and tests",
"status": "pending",
"priority": "high"
},
{
"content": "Run unprivileged tests, canonical typecheck, and reproducible artifact builds in /tmp/opencode",
"status": "pending",
"priority": "high"
},
{
"content": "Deliver evidence-backed PASS/CONCERN/MUST-FIX verdict separating source approval from host acceptance",
"status": "pending",
"priority": "high"
}
]
/home/byk/.local/share/opencode-v2-pilot/supervisor/review-source-hash /home/byk/.local/share/opencode-v2-pilot/supervisor/verify-readiness /home/byk/.local/share/opencode-v2-pilot/supervisor/ROOT-ACCEPTANCE.md /home/byk/.local/share/opencode-v2-pilot/supervisor/PROTOCOL.md /home/byk/.local/share/opencode-v2-pilot/supervisor/bin/opencode-pty-client /home/byk/.local/share/opencode-v2-pilot/supervisor/bin/opencode-pty-launcher /home/byk/.local/share/opencode-v2-pilot/supervisor/bin/opencode-pty-supervisor /home/byk/.local/share/opencode-v2-pilot/supervisor/opencode-pty.slice /home/byk/.local/share/opencode-v2-pilot/supervisor/opencode-pty-supervisor.service /home/byk/.local/share/opencode-v2-pilot/supervisor/go.sum /home/byk/.local/share/opencode-v2-pilot/supervisor/cmd/client/main_test.go /home/byk/.local/share/opencode-v2-pilot/supervisor/cmd/client/main.go /home/byk/.local/share/opencode-v2-pilot/supervisor/cmd/supervisor/main.go /home/byk/.local/share/opencode-v2-pilot/supervisor/cmd...
/home/byk/.local/share/opencode-v2-pilot/supervisor/bin/opencode-pty-client /home/byk/.local/share/opencode-v2-pilot/supervisor/bin/opencode-pty-launcher /home/byk/.local/share/opencode-v2-pilot/supervisor/bin/opencode-pty-supervisor /home/byk/.local/share/opencode-v2-pilot/supervisor/opencode-pty.slice /home/byk/.local/share/opencode-v2-pilot/supervisor/opencode-pty-supervisor.service /home/byk/.local/share/opencode-v2-pilot/CUTOVER.md /home/byk/.local/share/opencode-v2-pilot/config/opencode/tsconfig.json /home/byk/.local/share/opencode-v2-pilot/config/opencode/node_modules/detect-libc/package.json /home/byk/.local/share/opencode-v2-pilot/config/opencode/node_modules/node-gyp-build-optional-packages/package.json /home/byk/.local/share/opencode-v2-pilot/config/opencode/node_modules/csstype/package.json /home/byk/.local/share/opencode-v2-pilot/config/opencode/node_modules/msgpackr-extract/package.json /home/byk/.local/share/opencode-v2-pilot/config/opencode/node_modules/pure-rand/packag...
ripgrep execution failed
<path>/home/byk/.local/share/opencode-v2-pilot</path> <type>directory</type> <entries> cache/ config/ CUTOVER.md data/ opencode-v2.service state/ supervisor/ (7 entries) </entries>
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/review-source-hash</path> <type>file</type> <content> 1: #!/bin/sh 2: 3: set -eu 4: 5: ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) 6: ( 7: /usr/bin/find "$ROOT/supervisor/cmd" "$ROOT/supervisor/internal" -type f \( -name '*.go' -o -name '*_test.go' \) -print 8: /usr/bin/find /home/byk/Code/opencode-v2-pilot/packages/plugin/src -type f -name '*.ts' -print 9: printf '%s\n' \ 10: "$ROOT/supervisor/go.mod" \ 11: "$ROOT/supervisor/go.sum" \ 12: "$ROOT/supervisor/opencode-pty.slice" \ 13: "$ROOT/supervisor/opencode-pty-supervisor.service" \ 14: "$ROOT/config/opencode/plugins/pty.ts" \ 15: "$ROOT/config/opencode/plugins/pty-transport.ts" \ 16: "$ROOT/config/opencode/tsconfig.json" \ 17: "$ROOT/config/opencode/package.json" \ 18: "$ROOT/config/opencode/bun.lock" \ 19: "$ROOT/opencode-v2.service" \ 20: /home/byk/Code/opencode-v2-pilot/packages/plugin/package.json \ 21: ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/verify-readiness</path>
<type>file</type>
<content>
1: #!/bin/sh
2:
3: set -eu
4:
5: MARKER=/etc/opencode/pty-supervisor-verified
6: EXPECTED_REVISION='revision=opencode-v2-pilot:git:2ac698d65aa4690a694307e9cbdf44537ea9a4fb;pty-source:sha256:fff146df36754bc59d473a070985c4310cb57bdad64473ec7f68b5be5014286f'
7:
8: fail() {
9: printf '%s\n' "$1" >&2
10: exit 1
11: }
12:
13: [ -f "$MARKER" ] && [ ! -L "$MARKER" ] || fail 'PTY readiness marker is not a regular file'
14: [ "$(/usr/bin/stat -c '%u:%g:%a' "$MARKER")" = '0:0:644' ] || fail 'PTY readiness marker ownership or mode is invalid'
15: exec 3<"$MARKER"
16: IFS= read -r revision <&3 || fail 'PTY readiness marker is missing revision'
17: IFS= read -r supervisor <&3 || fail 'PTY readiness marker is missing supervisor hash'
18: IFS= read -r launcher <&3 || fail 'PTY readiness marker is missing launcher hash'
19: IFS= read -r client <&3 || fail 'PTY readiness marker is missing ...
<path>/home/byk/.local/share/opencode-v2-pilot/CUTOVER.md</path> <type>file</type> <content> 1: # OpenCode V2 cutover 2: 3: The V2 executable serves the API and web UI from one origin. Do not add nginx. 4: 5: ## Preflight 6: 7: 1. Confirm production is still healthy on port 4096. 8: 2. Confirm the candidate revision and smoke build: 9: `git -C /home/byk/Code/opencode-v2-pilot rev-parse HEAD` 10: `/home/byk/Code/opencode-v2-pilot/packages/cli/dist-v2-pilot-final/cli-node-linux-x64/bin/opencode2-node --version` 11: 3. Confirm the isolated candidate on port 14102: 12: `curl --fail --user opencode:$OPENCODE_PASSWORD http://127.0.0.1:14102/api/health` 13: `curl --fail http://127.0.0.1:14102/ >/dev/null` 14: 4. Confirm both local plugins are active after calling `POST /api/plugin/await-activation`. 15: 5. Create `/home/byk/.local/share/opencode-v2-pilot/server.env` with mode `0600` and one line: `OPENCODE_PASSWORD=<password>`. 16: 6. ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/ROOT-ACCEPTANCE.md</path> <type>file</type> <content> 1: # Root-only acceptance 2: 3: Do not install, start, enable, or mark the candidate ready until every check below passes on the exact target host. Source tests never substitute for these checks. 4: 5: 1. Rebuild all three binaries twice from the reviewed source with `CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags=-buildid=`. Require both build sets to match. Record the content-bound source revision, Go version, dependency sums, complete build commands, and SHA-256 hashes. ...
/tmp/opencode/pty-plugin-smoke-final-10.json /tmp/opencode/pty-plugin-smoke-review-6.json /tmp/opencode/pty-smoke-tsconfig.json /tmp/opencode/pty-plugin-smoke-current-9.json /tmp/opencode/pty-plugin-smoke-fixes-proof-3.json /tmp/opencode/pty-plugin-smoke-fixes-final-9.json /tmp/opencode/pty-tsconfig.json /tmp/opencode/pty-plugin-smoke-final-proof-9.json /tmp/opencode/review-opencode-pty-supervisor /tmp/opencode/opencode-pty-supervisor-b /tmp/opencode/pty-review-fresh-a/opencode-pty-client /tmp/opencode/pty-review-fresh-a/opencode-pty-supervisor /tmp/opencode/pty-review-fresh-a/opencode-pty-launcher /tmp/opencode/pty-plugin-smoke-review-4.json /tmp/opencode/pty-plugin-smoke-fixes-proof-10.json /tmp/opencode/pty-plugin-smoke-fixes-final-3.json /tmp/opencode/pty-plugin-smoke-fixes-proof-8.json /tmp/opencode/opencode-pty-launcher-final-b /tmp/opencode/pty-plugin-smoke-fixes-1.json /tmp/opencode/opencode-pty-client-b /tmp/opencode/pty-plugin-smoke-fixes-4.json /tmp/opencode/pty-plugin-smoke...
Found 100 matches (more matches available) /home/byk/.local/share/opencode-v2-pilot/supervisor/ROOT-ACCEPTANCE.md: Line 39: 14. Run `bun /tmp/opencode/pty-plugin-smoke.ts` ten times. Keep that reviewed harness outside the auto-discovered plugin directory. Then run it against the freshly built helper and an isolated disposable supervisor. Confirm permissions, source identity, ownership, deletion, in-flight deletion, reservations, JSON envelopes, regex bounds, UTF-8 write bounds, pre-listener output bounds, saturated STOP bounds, transport framing, helper transfer, notifications, timeouts, and cleanup. /home/byk/.local/share/opencode-v2-pilot/supervisor/PROTOCOL.md: Line 48: The transient launcher receives the PTY stream as stdin/stdout and the approved cwd descriptor as stderr. It calls `fchdir(2)`, replaces stderr with stdout, validates only canonical `a[A-Za-z0-9_-]*` URL-safe unpadded base64 arguments, clears the environment, and binds its own reviewed executable to fd 3. ...
fff146df36754bc59d473a070985c4310cb57bdad64473ec7f68b5be5014286f ff03df72fc6a401e8070db776ceba524e9111d9d907c6f4939244354564a86f2 bin/opencode-pty-supervisor d833c859476f021565e8f425e6ee51353909060fa5f64ce629fb07d3411987dd bin/opencode-pty-launcher fb8739d98ff7882782005e04ef731b6120e8daf0719e606362a1fe620adc2cde bin/opencode-pty-client bin/opencode-pty-supervisor regular file byk:byk 755 4430463 bin/opencode-pty-launcher regular file byk:byk 755 2098942 bin/opencode-pty-client regular file byk:byk 755 2109912 review-source-hash regular file byk:byk 755 965 verify-readiness regular file byk:byk 755 1376 go version go1.22.2 linux/amd64 1.3.14 v24.16.0
No files found
The manifest and all three artifact hashes match exactly. The review host currently provides Node v24.16.0, so it cannot satisfy the required final Node 26.4 inheritance gate; I will treat that as a deployment-acceptance blocker, not a source defect, while continuing the source review.
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/supervisor/server.go</path>
<type>file</type>
<content>
1: package supervisor
2:
3: import (
4: "context"
5: "crypto/rand"
6: "encoding/binary"
7: "errors"
8: "fmt"
9: "io"
10: "log"
11: "net"
12: "os"
13: "os/user"
14: "strconv"
15: "sync"
16: "syscall"
17: "time"
18: "unicode/utf8"
19:
20: "opencode-pty-supervisor/internal/protocol"
21:
22: "golang.org/x/sys/unix"
23: )
24:
25: const (
26: socketPath = "/run/opencode-pty/supervisor.sock"
27: maxSessions = 16
28: maxUnauthenticated = 32
29: maxAdmissionsPerMinute = 120
30: maxStartDescriptors = 8
31: socketBufferSize = 128 * 1024
32: handshakeTimeout = 5 * time.Second
33: )
34:
35: var errStopRequested = errors.New("client requested stop")
36:
37: type Server struct {
38: manager unitManager
39: listener *net.UnixListener
40: sessions chan struct{}
41: unauthenticated ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/supervisor/systemd.go</path> <type>file</type> <content> 1: package supervisor 2: 3: import ( 4: "context" 5: "encoding/base64" 6: "errors" 7: "fmt" 8: "net" 9: "os" 10: "regexp" 11: "sync" 12: "time" 13: 14: systemddbus "github.com/coreos/go-systemd/v22/dbus" 15: "github.com/godbus/dbus/v5" 16: ) 17: 18: const ( 19: clientService = "opencode-v2.service" 20: supervisorService = "opencode-pty-supervisor.service" 21: ptySlice = "opencode-pty.slice" 22: expectedClientCgroup = "/system.slice/opencode-v2.service" 23: launcherPath = "/usr/local/libexec/opencode-pty-launcher" 24: unitPrefix = "opencode-pty-" 25: unitSuffix = ".service" 26: operationTimeout = 5 * time.Second 27: stopTimeout = 15 * time.Second 28: outputDrainTimeout = 2 * time.Second 29: stateQueryInterval = 100 * time.Millisecond 30: defaultRuntimeSec = 3600 31: ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/supervisor/auth.go</path>
<type>file</type>
<content>
1: package supervisor
2:
3: import (
4: "bytes"
5: "context"
6: "errors"
7: "fmt"
8: "net"
9:
10: "golang.org/x/sys/unix"
11: )
12:
13: type authenticatedPeer struct {
14: credential *unix.Ucred
15: pidfd int
16: identity clientIdentity
17: }
18:
19: func authenticate(ctx context.Context, connection *net.UnixConn, manager unitManager, expectedUID uint32, expectedGID uint32) (*authenticatedPeer, error) {
20: credential, pidfd, err := peerIdentity(connection)
21: if err != nil {
22: return nil, err
23: }
24: peer := &authenticatedPeer{credential: credential, pidfd: pidfd}
25: if err := peer.validateCredentials(expectedUID, expectedGID); err != nil {
26: peer.Close()
27: return nil, err
28: }
29: identity, err := manager.ClientState(ctx)
30: if err != nil {
31: peer.Close()
32: return nil, fmt.Errorf("query client service: %w", ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/protocol/frame.go</path>
<type>file</type>
<content>
1: package protocol
2:
3: import (
4: "encoding/binary"
5: "errors"
6: "fmt"
7: "io"
8: "strings"
9: "unicode/utf8"
10: )
11:
12: const (
13: HeaderSize = 12
14: MaxFrameSize = 70 * 1024
15: MaxIOPayloadSize = 32 * 1024
16: Version = 1
17:
18: TypeStart = 1
19: TypeInput = 2
20: TypeOutput = 3
21: TypeExit = 4
22: TypeError = 5
23: TypeStarted = 6
24: TypeStop = 7
25: TypeStopped = 8
26:
27: MaxArgs = 128
28: MaxCommandSize = 4096
29: MaxArgSize = 16384
30: MaxArgsSize = 65536
31: MaxRuntimeSec = 3600
32: )
33:
34: var (
35: magic = [4]byte{'O', 'P', 'T', 'Y'}
36: ErrInvalidFrame = errors.New("invalid frame")
37: ErrFrameTooLarge = errors.New("frame too large")
38: )
39:
40: type Frame struct {
41: Type byte
42: Payload []byte
43: }
44:
45: type Start struct {
46: Device ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/cmd/launcher/main.go</path>
<type>file</type>
<content>
1: package main
2:
3: import (
4: "encoding/base64"
5: "errors"
6: "fmt"
7: "os"
8: "strings"
9: "syscall"
10:
11: "opencode-pty-supervisor/internal/protocol"
12:
13: "golang.org/x/sys/unix"
14: )
15:
16: const encodedArgumentsEnvironment = "OPENCODE_PTY_ARGV"
17:
18: const launcherFD = 3
19:
20: func main() {
21: if err := run(os.Args[1:]); err != nil {
22: fmt.Fprintln(os.Stderr, err)
23: os.Exit(1)
24: }
25: }
26:
27: func run(values []string) error {
28: if len(values) == 1 && values[0] == "--exec" {
29: return execCommand()
30: }
31: if _, err := decodeArguments(values); err != nil {
32: return err
33: }
34: if err := syscall.Fchdir(2); err != nil {
35: return fmt.Errorf("fchdir approved cwd: %w", err)
36: }
37: if err := syscall.Dup2(1, 2); err != nil {
38: return fmt.Errorf("replace cwd descriptor: %w", err)
39: }
40: if err := ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/cmd/client/main.go</path>
<type>file</type>
<content>
1: package main
2:
3: import (
4: "encoding/base64"
5: "errors"
6: "fmt"
7: "os"
8: "strconv"
9: "strings"
10: "syscall"
11:
12: "opencode-pty-supervisor/internal/protocol"
13:
14: "golang.org/x/sys/unix"
15: )
16:
17: const (
18: socketFD = 3
19: cwdFD = 4
20: )
21:
22: func main() {
23: if err := sendStart(socketFD, cwdFD, os.Args[1:]); err != nil {
24: fmt.Fprintln(os.Stderr, err)
25: os.Exit(1)
26: }
27: }
28:
29: func sendStart(socket, cwd int, values []string) error {
30: unix.CloseOnExec(socket)
31: unix.CloseOnExec(cwd)
32: if _, err := unix.Getpeername(socket); err != nil {
33: return fmt.Errorf("validate inherited connected socket: %w", err)
34: }
35: var stat unix.Stat_t
36: if err := unix.Fstat(cwd, &stat); err != nil {
37: return fmt.Errorf("inspect inherited cwd: %w", err)
38: }
39: if stat.Mode&unix.S_IFMT != unix.S_IFDIR ...
<path>/home/byk/.local/share/opencode-v2-pilot/config/opencode/plugins/pty-transport.ts</path>
<type>file</type>
<content>
1: import { spawn } from "node:child_process"
2: import type { ChildProcess } from "node:child_process"
3: import { isUtf8 } from "node:buffer"
4: import { fstatSync } from "node:fs"
5: import { stat } from "node:fs/promises"
6: import type { FileHandle } from "node:fs/promises"
7: import { createConnection } from "node:net"
8: import type { Socket } from "node:net"
9:
10: const MAGIC = Buffer.from("OPTY")
11: const VERSION = 1
12: const HEADER_SIZE = 12
13: const MAX_FRAME_SIZE = 70 * 1024
14: const MAX_IO_PAYLOAD_SIZE = 32 * 1024
15: const TYPE_INPUT = 2
16: const TYPE_OUTPUT = 3
17: const TYPE_EXIT = 4
18: const TYPE_ERROR = 5
19: const TYPE_STARTED = 6
20: const TYPE_STOP = 7
21: const TYPE_STOPPED = 8
22: const DEFAULT_SOCKET_PATH = "/run/opencode-pty/supervisor.sock"
23: const DEFAULT_HELPER_PATH = "/usr/local/libexec/opencode-pty-client"
24: const ...
<path>/home/byk/.local/share/opencode-v2-pilot/config/opencode/plugins/pty.ts</path>
<type>file</type>
<content>
1: import { Plugin } from "@opencode/plugin"
2: import type { Context } from "@opencode/plugin/plugin"
3: import type { ToolContext } from "@opencode/plugin/tool"
4: import { Schema } from "effect"
5: import { spawn } from "node:child_process"
6: import { open, realpath } from "node:fs/promises"
7: import type { FileHandle } from "node:fs/promises"
8: import { constants } from "node:fs"
9: import { assertSupervisorAvailable, MAX_BUFFER_SIZE, openSupervisorTransport } from "./pty-transport"
10: import type { SupervisorOptions, SupervisorTransport } from "./pty-transport"
11:
12: type PtyPluginOptions = SupervisorOptions & {
13: assertAvailable?: typeof assertSupervisorAvailable
14: openTransport?: typeof openSupervisorTransport
15: }
16:
17: const MAX_SESSIONS = 16
18: const MAX_SESSIONS_PER_OWNER = 5
19: const DEFAULT_READ_LIMIT = 500
20: const MAX_READ_LIMIT = ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/PROTOCOL.md</path> <type>file</type> <content> 1: # PTY supervisor protocol 2: 3: The protocol uses one Unix `SOCK_STREAM` connection for one PTY. The Node SEA process opens and retains the connection. The supervisor authenticates that connection's immutable peer credentials against the exact `opencode-v2.service` MainPID. The client helper never initiates a socket connection, resolves a caller path, or opens an application-selected path. The Go runtime may read reviewed host metadata such as `/sys/kernel/mm/transparent_hugepage/hpage_pmd_size`. Node starts the fixed root-owned helper with duplicates of the connected socket at fd 3 and the approved directory at fd 4. The helper sends the start frame and fd 4, then exits. Exact Node 26.4 SEA descriptor inheritance and same-UID delegation remain target-host acceptance blockers; source behavior never proves that all other Node child processes inherit neither descriptor. ...
<path>/home/byk/.local/share/opencode-v2-pilot/opencode-v2.service</path> <type>file</type> <content> 1: [Unit] 2: Description=OpenCode V2 Server 3: After=network.target opencode-pty-supervisor.service 4: Requires=opencode-pty-supervisor.service 5: 6: [Service] 7: Type=simple 8: EnvironmentFile=/home/byk/.opencode/env 9: EnvironmentFile=/home/byk/.local/share/opencode-v2-pilot/server.env 10: Environment=OPENCODE_CONFIG_DIR=/home/byk/.local/share/opencode-v2-pilot/config/opencode 11: Environment=OPENCODE_DB=/home/byk/.local/share/opencode-v2-pilot/data/opencode/opencode.db 12: Environment=XDG_DATA_HOME=/home/byk/.local/share/opencode-v2-pilot/data 13: Environment=XDG_CACHE_HOME=/home/byk/.local/share/opencode-v2-pilot/cache 14: Environment=XDG_CONFIG_HOME=/home/byk/.local/share/opencode-v2-pilot/config 15: Environment=XDG_STATE_HOME=/home/byk/.local/share/opencode-v2-pilot/state 16: User=byk 17: WorkingDirectory=/home/byk 18: ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/opencode-pty-supervisor.service</path> <type>file</type> <content> 1: [Unit] 2: Description=OpenCode PTY supervisor 3: After=dbus.service 4: Requires=dbus.service 5: 6: [Service] 7: Type=exec 8: User=root 9: Group=byk 10: SupplementaryGroups= 11: ExecStart=/usr/local/libexec/opencode-pty-supervisor 12: RuntimeDirectory=opencode-pty 13: RuntimeDirectoryMode=0750 14: RuntimeDirectoryPreserve=no 15: NoNewPrivileges=yes 16: CapabilityBoundingSet= 17: AmbientCapabilities= 18: UMask=0077 19: KillMode=control-group 20: KillSignal=SIGTERM 21: FinalKillSignal=SIGKILL 22: SendSIGKILL=yes 23: TimeoutStopSec=20s 24: OOMPolicy=kill 25: Delegate=no 26: RestrictAddressFamilies=AF_UNIX 27: PrivateTmp=yes 28: PrivateDevices=yes 29: PrivateMounts=yes 30: PrivateNetwork=yes 31: ProtectSystem=strict 32: ProtectHome=yes 33: ProtectKernelTunables=yes 34: ProtectKernelModules=yes 35: ProtectKernelLogs=yes 36: ProtectControlGroups=yes 37: ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/opencode-pty.slice</path> <type>file</type> <content> 1: [Unit] 2: Description=OpenCode isolated PTY sessions 3: Before=slices.target 4: 5: [Slice] 6: CPUAccounting=yes 7: MemoryAccounting=yes 8: TasksAccounting=yes 9: IOAccounting=yes 10: CPUQuota=800% 11: IOWeight=100 12: MemoryHigh=1536M 13: MemoryMax=2G 14: TasksMax=512 (End of file - total 14 lines) </content>
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/cmd/supervisor/main.go</path>
<type>file</type>
<content>
1: package main
2:
3: import (
4: "context"
5: "fmt"
6: "os"
7: "os/signal"
8: "syscall"
9:
10: "opencode-pty-supervisor/internal/supervisor"
11: )
12:
13: func main() {
14: ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
15: defer cancel()
16: manager, err := supervisor.NewSystemdManager(ctx)
17: if err != nil {
18: fmt.Fprintln(os.Stderr, err)
19: os.Exit(1)
20: }
21: defer manager.Close()
22: server, err := supervisor.NewServer(manager)
23: if err != nil {
24: fmt.Fprintln(os.Stderr, err)
25: os.Exit(1)
26: }
27: if err := server.Serve(ctx); err != nil {
28: fmt.Fprintln(os.Stderr, err)
29: os.Exit(1)
30: }
31: }
(End of file - total 31 lines)
</content>
Found 45 matches
/home/byk/.local/share/opencode-v2-pilot/supervisor/cmd/client/main_test.go:
Line 20: func TestNodePassesConnectedSocketWithoutChangingPeerMainPID(t *testing.T) {
Line 126: func TestSendStartTransfersExactlyOneCloexecDirectoryDescriptor(t *testing.T) {
Line 181: func TestDecodeStartEnforcesCommandArgumentAndAggregateLimits(t *testing.T) {
/home/byk/.local/share/opencode-v2-pilot/supervisor/cmd/launcher/main_test.go:
Line 13: func TestDecodeArgumentsPreservesEveryArgument(t *testing.T) {
Line 30: func TestDecodeArgumentsRejectsInvalidGrammar(t *testing.T) {
Line 36: func TestScriptArgumentsRequireInteractiveShellAndExitPropagation(t *testing.T) {
Line 44: func TestLauncherExecutesInDescriptorDirectory(t *testing.T) {
Line 64: func TestLauncherPropagatesExitAndSignalStatus(t *testing.T) {
Line 97: func TestLauncherPreservesMetacharactersAndNewlinesWithoutEvaluation(t *testing.T) ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/supervisor/systemd_test.go</path>
<type>file</type>
<content>
1: package supervisor
2:
3: import (
4: "context"
5: "errors"
6: "os"
7: "os/exec"
8: "strings"
9: "testing"
10: "time"
11:
12: systemddbus "github.com/coreos/go-systemd/v22/dbus"
13: "github.com/godbus/dbus/v5"
14: )
15:
16: func TestUnitNameGrammar(t *testing.T) {
17: valid := "opencode-pty-0123456789abcdef0123456789abcdef.service"
18: if !validUnitName(valid) {
19: t.Fatalf("rejected %q", valid)
20: }
21: for _, invalid := range []string{
22: "opencode-pty-.service",
23: "opencode-pty-0123456789ABCDEF0123456789ABCDEF.service",
24: "opencode-pty-0123456789abcdef0123456789abcdef.scope",
25: "opencode-pty-0123456789abcdef0123456789abcdef.service/../x",
26: } {
27: if validUnitName(invalid) {
28: t.Fatalf("accepted %q", invalid)
29: }
30: }
31: }
32:
33: func TestWaitForJobResultRejectsClosedNonDoneAndTimeout(t *testing.T) ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/supervisor/server_test.go</path>
<type>file</type>
<content>
1: package supervisor
2:
3: import (
4: "bytes"
5: "context"
6: "encoding/binary"
7: "encoding/json"
8: "errors"
9: "fmt"
10: "io"
11: "net"
12: "os"
13: "os/exec"
14: "path/filepath"
15: "sync"
16: "syscall"
17: "testing"
18: "time"
19:
20: "opencode-pty-supervisor/internal/protocol"
21:
22: "golang.org/x/sys/unix"
23: )
24:
25: type sessionManager struct {
26: startErr error
27: wait chan unitResult
28: stop func() error
29: stopped chan struct{}
30: once sync.Once
31: identity int
32: }
33:
34: func (manager *sessionManager) ClientState(context.Context) (clientIdentity, error) {
35: manager.identity++
36: return currentIdentity(), nil
37: }
38:
39: func (manager *sessionManager) Start(context.Context, string, protocolCommand, *os.File, *os.File, uint32) error {
40: return manager.startErr
41: }
42:
43: func ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/cmd/client/main_test.go</path>
<type>file</type>
<content>
1: package main
2:
3: import (
4: "bytes"
5: "encoding/base64"
6: "encoding/json"
7: "fmt"
8: "net"
9: "os"
10: "os/exec"
11: "path/filepath"
12: "strings"
13: "testing"
14:
15: "opencode-pty-supervisor/internal/protocol"
16:
17: "golang.org/x/sys/unix"
18: )
19:
20: func TestNodePassesConnectedSocketWithoutChangingPeerMainPID(t *testing.T) {
21: if os.Getenv("OPENCODE_CLIENT_HELPER_TEST") == "1" {
22: encoded := func(value string) string { return "a" + base64.RawURLEncoding.EncodeToString([]byte(value)) }
23: if err := sendStart(socketFD, cwdFD, []string{"60", encoded("/bin/true")}); err != nil {
24: t.Fatal(err)
25: }
26: return
27: }
28: node, err := exec.Command("node", "-p", "process.execPath").Output()
29: if err != nil {
30: t.Skip("node runtime is unavailable")
31: }
32: socketPath := filepath.Join(t.TempDir(), ...
<path>/home/byk/.local/share/opencode-v2-pilot/config/opencode/tsconfig.json</path>
<type>file</type>
<content>
1: {
2: "compilerOptions": {
3: "allowImportingTsExtensions": true,
4: "lib": ["ESNext", "DOM", "DOM.Iterable"],
5: "module": "Preserve",
6: "moduleResolution": "Bundler",
7: "noEmit": true,
8: "paths": {
9: "@opencode/plugin": ["/home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/index.ts"],
10: "@opencode/plugin/*": ["/home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/*.ts"]
11: },
12: "skipLibCheck": true,
13: "strict": true,
14: "target": "ESNext",
15: "types": ["bun"]
16: },
17: "include": ["plugins/**/*.ts", "test/**/*.ts"]
18: }
(End of file - total 18 lines)
</content>
<path>/home/byk/.local/share/opencode-v2-pilot/config/opencode/package.json</path>
<type>file</type>
<content>
1: {
2: "private": true,
3: "type": "module",
4: "dependencies": {
5: "effect": "file:/home/byk/Code/opencode-v2-pilot/node_modules/.bun/effect@4.0.0-rc.112/node_modules/effect"
6: },
7: "devDependencies": {
8: "@types/bun": "1.2.21"
9: }
10: }
(End of file - total 10 lines)
</content>
/home/byk/.local/share/opencode-v2-pilot/config/opencode/test/followup.test.ts
/home/byk/Code/opencode-v2-pilot/packages/server/test/pty-socket.test.ts /home/byk/Code/opencode-v2-pilot/packages/server/test/persistent-pty.test.ts /home/byk/Code/opencode-v2-pilot/packages/server/src/pty-environment.ts /home/byk/Code/opencode-v2-pilot/packages/server/src/handlers/pty.ts /home/byk/Code/opencode-v2-pilot/packages/server/src/handlers/pty-socket.ts /home/byk/Code/opencode-v2-pilot/packages/server/src/handlers/persistent-pty.ts /home/byk/Code/opencode-v2-pilot/packages/schema/src/persistent-pty.ts /home/byk/Code/opencode-v2-pilot/packages/schema/src/pty.ts /home/byk/Code/opencode-v2-pilot/packages/schema/src/pty-ticket.ts /home/byk/Code/opencode-v2-pilot/packages/protocol/src/groups/pty.ts /home/byk/Code/opencode-v2-pilot/packages/protocol/src/groups/persistent-pty.ts /home/byk/Code/opencode-v2-pilot/packages/client/test/solid-pty.test.ts /home/byk/Code/opencode-v2-pilot/packages/client/src/solid/pty.ts /home/byk/Code/opencode-v2-pilot/packages/client/src/pty-handoff.ts ...
M packages/core/src/plugin/host.ts M packages/core/test/plugin.test.ts M packages/core/test/plugin/fixture.ts M packages/core/test/plugin/host.ts M packages/plugin/src/effect/permission.ts M packages/plugin/src/promise/adapter.ts M packages/plugin/src/promise/permission.ts ?? packages/cli/dist-v2-pilot-final/ ?? packages/cli/dist-v2-pilot-next/ ?? packages/cli/dist-v2-pilot/ 2ac698d65aa4690a694307e9cbdf44537ea9a4fb
The source manifest also covers every TypeScript file in packages/plugin/src, and the checkout has six uncommitted plugin/core files at commit 2ac698d65aa4690a694307e9cbdf44537ea9a4fb. I will inspect those exact changed files because they define permission/source identity and plugin shutdown behavior; the content hash, not the Git commit alone, is the reviewed identity.
diff --git a/packages/core/src/plugin/host.ts b/packages/core/src/plugin/host.ts
index 44beadcc6c..6abb955508 100644
--- a/packages/core/src/plugin/host.ts
+++ b/packages/core/src/plugin/host.ts
@@ -383,6 +383,7 @@ export const make = Effect.fn("PluginHost.make")(function* (
},
permission: {
hook: (name, callback) => hooks.register("permission", name, callback),
+ assert: permission.assert,
list: (input) => permission.forSession(input.sessionID),
get: (input) =>
permission
diff --git a/packages/core/test/plugin.test.ts b/packages/core/test/plugin.test.ts
index 1b71e18978..18a6966a62 100644
--- a/packages/core/test/plugin.test.ts
+++ b/packages/core/test/plugin.test.ts
@@ -1,20 +1,33 @@
import { expect } from "bun:test"
import path from "path"
-import { Clock, Deferred, Effect } from "effect"
+import { Cause, Clock, Deferred, Effect, Exit, Schema } from "effect"
import { TestClock } from "effect/testing"
+import { Agent } from ...
Found 8 matches
/home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/adapter.ts:
Line 82: const run = Effect.runPromiseWith(context)
Line 247: Effect.runPromiseWith(context)(effect).then((registration) => ({
Line 248: dispose: () => Effect.runPromiseWith(context)(registration.dispose),
Line 251: const run = <A, E>(effect: Effect.Effect<A, E>) => Effect.runPromiseWith(context)(effect)
Line 274: }).pipe(Effect.runPromiseWith(context))) as PromiseMethod
Line 425: active: (id) => Effect.runPromiseWith(context)(host.integration.connection.active(id)),
Line 426: resolve: (connection) => Effect.runPromiseWith(context)(host.integration.connection.resolve(connection)),
Line 617: progress: (update) => Effect.runPromise(context.progress(update)),
<path>/home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/adapter.ts</path>
<type>file</type>
<content>
60: return iterator.return?.() ?? Promise.resolve({ done: true as const, value: undefined })
61: }
62: const abort = () => {
63: void close()
64: }
65: subscriptions.add(close)
66: options?.signal?.addEventListener("abort", abort, { once: true })
67: if (options?.signal?.aborted) abort()
68: return {
69: next: () =>
70: iterator.next().then(
71: (result) => (result.done ? close().then(() => result) : result),
72: (error: unknown) => close().then(() => Promise.reject(error)),
73: ),
74: return: close,
75: }
76: },
77: })) satisfies StreamAdapter
78: })
79:
80: const rpcFromEffect = Effect.fn("Plugin.Rpc.fromEffect")(function* (host: HostRpc, streams: StreamAdapter) {
81: const context = yield* Effect.context<Scope.Scope>()
82: const run = ...
No files found
Found 15 matches
/home/byk/Code/opencode-v2-pilot/packages/core/src/permission.ts:
Line 64: export class DeclinedError extends Schema.TaggedError<DeclinedError>()("Permission.DeclinedError", {}) {}
Line 66: export class CorrectedError extends Schema.TaggedError<CorrectedError>()("Permission.CorrectedError", {
Line 85: export type Error = BlockedError | CorrectedError
Line 105: readonly assert: (input: AssertInput) => Effect.Effect<void, Error | SessionErrors.NotFoundError>
Line 117: readonly deferred: Deferred.Deferred<void, DeclinedError | CorrectedError>
Line 132: Effect.forEach(pending.values(), (item) => Deferred.fail(item.deferred, new DeclinedError()), {
Line 202: const deferred = yield* Deferred.make<void, DeclinedError | CorrectedError>()
Line 221: const assert = Effect.fn("Permission.assert")((input: AssertInput) =>
Line 240: // WITH feedback (CorrectedError) intentionally stays typed so the leaf can turn
Line ...
<path>/home/byk/Code/opencode-v2-pilot/packages/core/src/permission.ts</path>
<type>file</type>
<content>
215: const result = yield* evaluateInput(input)
216: const value = request(input, result.message)
217: if (result.effect === "ask") yield* create(value, input.agent)
218: return { id: value.id, effect: result.effect }
219: })
220:
221: const assert = Effect.fn("Permission.assert")((input: AssertInput) =>
222: Effect.gen(function* () {
223: const result = yield* evaluateInput(input)
224: return yield* Effect.uninterruptibleMask((restore) =>
225: Effect.gen(function* () {
226: if (result.effect === "deny") {
227: return yield* new BlockedError({
228: rules: relevant(input, result.rules),
229: permission: input.action,
230: resources: input.resources,
231: reason: result.message,
232: })
233: }
234: ...
<path>/tmp/opencode/pty-plugin-smoke.ts</path>
<type>file</type>
<content>
1: import { createPtyPlugin } from "/home/byk/.local/share/opencode-v2-pilot/config/opencode/plugins/pty.ts"
2: import { assertSupervisorAvailable } from "/home/byk/.local/share/opencode-v2-pilot/config/opencode/plugins/pty-transport.ts"
3: import type { SupervisorExit, SupervisorTransport } from "/home/byk/.local/share/opencode-v2-pilot/config/opencode/plugins/pty-transport.ts"
4: import { mkdir, symlink } from "node:fs/promises"
5:
6: const plugin = createPtyPlugin({
7: async assertAvailable() {},
8: async openTransport(_, command, args, runtimeSeconds) {
9: let listener: ((data: Buffer) => void) | undefined
10: const queued: Buffer[] = []
11: let done = (_: SupervisorExit) => {}
12: let settled = false
13: const exited = new Promise<SupervisorExit>((resolve) => {
14: done = resolve
15: })
16: const finish = (exit: SupervisorExit) => {
17: if (settled) return
18: settled = true
19: ...
<path>/tmp/opencode/pty-smoke-tsconfig.json</path>
<type>file</type>
<content>
1: {
2: "compilerOptions": {
3: "allowImportingTsExtensions": true,
4: "module": "Preserve",
5: "moduleResolution": "Bundler",
6: "noEmit": true,
7: "paths": {
8: "@opencode/plugin": ["/tmp/opencode/pty-plugin-stub.ts"]
9: },
10: "target": "ESNext"
11: }
12: }
(End of file - total 12 lines)
</content>
<path>/tmp/opencode/pty-tsconfig.json</path>
<type>file</type>
<content>
1: {
2: "compilerOptions": {
3: "allowImportingTsExtensions": true,
4: "lib": ["ESNext", "DOM", "DOM.Iterable"],
5: "module": "Preserve",
6: "moduleResolution": "Bundler",
7: "noEmit": true,
8: "paths": {
9: "@opencode/plugin": ["/home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/index.ts"],
10: "@opencode/plugin/*": ["/home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/*.ts"],
11: "effect": ["/home/byk/Code/opencode-v2-pilot/node_modules/.bun/effect@4.0.0-rc.112/node_modules/effect/dist/index.d.ts"],
12: "effect/*": ["/home/byk/Code/opencode-v2-pilot/node_modules/.bun/effect@4.0.0-rc.112/node_modules/effect/dist/*.d.ts"]
13: },
14: "skipLibCheck": true,
15: "strict": true,
16: "target": "ESNext",
17: "typeRoots": [
18: "/home/byk/.local/share/opencode-v2-pilot/config/opencode/node_modules/@types",
19: ...
No files found
Found 35 matches /home/byk/Code/opencode-v2-pilot/packages/sdk/package.json: Line 27: "typecheck": "tsgo -b", /home/byk/Code/opencode-v2-pilot/services/updates/package.json: Line 12: "typecheck": "tsgo --noEmit" /home/byk/Code/opencode-v2-pilot/services/files/package.json: Line 10: "typecheck": "tsgo --noEmit" /home/byk/Code/opencode-v2-pilot/package.json: Line 124: "oxlint-tsgolint": "0.21.0", /home/byk/Code/opencode-v2-pilot/packages/plugin-browser/package.json: Line 26: "typecheck": "tsgo --noEmit -p tsconfig.test.json", /home/byk/Code/opencode-v2-pilot/packages/latex/package.json: Line 13: "typecheck": "tsgo --noEmit" /home/byk/Code/opencode-v2-pilot/packages/util/package.json: Line 37: "typecheck": "tsgo --noEmit", /home/byk/Code/opencode-v2-pilot/packages/httpapi-codegen/package.json: Line 12: "typecheck": "tsgo --noEmit" /home/byk/Code/opencode-v2-pilot/packages/http-recorder/package.json: Line 31: ...
No files found
(no output)
<path>/home/byk/Code/opencode-v2-pilot/packages/core/test/persistent-pty-daemon.test.ts</path>
<type>file</type>
<content>
1: import { expect } from "bun:test"
2: import { spawn } from "node:child_process"
3: import { mkdtemp, rm, writeFile } from "node:fs/promises"
4: import net from "node:net"
5: import os from "node:os"
6: import path from "node:path"
7: import { Effect } from "effect"
8: import { makeDaemonTransport } from "../src/persistent-pty/daemon"
9: import { it } from "./lib/effect"
10:
11: const pong = { type: "pong", instance_id: "test", pid: process.pid, protocol: 7 }
12:
13: it.live("rediscovers a same-protocol daemon after its registration rotates", () =>
14: Effect.gen(function* () {
15: const directory = yield* temporaryDirectory()
16: const socketPath = path.join(directory, "daemon.sock")
17: let token = "old-token"
18: let instance = "old-instance"
19: let creates = 0
20: yield* listen(socketPath, (_socket, request, receivedToken) => ...
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/supervisor/auth_test.go</path>
<type>file</type>
<content>
1: package supervisor
2:
3: import (
4: "context"
5: "os"
6: "testing"
7: )
8:
9: type authenticationManager struct {
10: identity clientIdentity
11: }
12:
13: func (manager *authenticationManager) ClientState(context.Context) (clientIdentity, error) {
14: return manager.identity, nil
15: }
16:
17: func (*authenticationManager) Start(context.Context, string, protocolCommand, *os.File, *os.File, uint32) error {
18: return nil
19: }
20:
21: func (*authenticationManager) StopAndWait(context.Context, string) error { return nil }
22: func (*authenticationManager) Wait(context.Context, string) (unitResult, error) {
23: return unitResult{}, nil
24: }
25: func (*authenticationManager) CleanupOrphans(context.Context) error { return nil }
26: func (*authenticationManager) Close() {}
27:
28: func currentIdentity() clientIdentity ...
Two binding risks need deeper verification. The manifest hashes packages/plugin/src but omits the uncommitted Core host change that exposes ctx.permission.assert, and it omits the executable readiness verifier; I am checking whether the candidate binary or another immutable artifact closes either gap before classifying them.
8f7a60bdd3391142028ffd8fd105a6807c7cdf1cdd7447fb347bcf3c1871dbda verify-readiness f231f9f8c57fbcadda3a32c7559cd3e45421647312269e04a6798187566584f6 review-source-hash 066ad0a2171eb2591be8cf5465cb7caeadb5c6ab90ddd662d76c3e240e185e58 ROOT-ACCEPTANCE.md 0066936168c35d2e0162f182d76feaa37c42b1499feb061972cb9343b8c7f257 PROTOCOL.md 1c6fb3e2199f7475f2020981cb8eac05cdded6083291b5cab7e997068fdb48fd ../CUTOVER.md 07181f554cf14fe2608b759a048870353bb4b440c0be9d06126464e6f36b1612 ../opencode-v2.service 07196988cfa0e34e77927d4ec5e208a5e7ea66192b70af0dde27a9a049ee92b5 ../config/opencode/tsconfig.json cbe806483294fe4b7fe9c5fa98723ccbfe0baa8ab202a030b08c0cdf097af2e9 ../config/opencode/package.json ae666b20da50bcd40fcd02b80de781c9907d9902c68106adc5c1d79aa28e6408 ../config/opencode/plugins/pty.ts e464229acac2e97f1e24c93b59a075286838bd3307a4f9c778cda57337574ce3 ../config/opencode/plugins/pty-transport.ts ../opencode-v2.service regular file byk:byk 644 1251 ../config/opencode/tsconfig.json ...
67ecda49fa5be3ddb8f7fcb20a33f008a88dea093f0b8c8b10144afa0130f7cf packages/cli/dist-v2-pilot-final/cli-node-linux-x64/bin/opencode2-node packages/cli/dist-v2-pilot-final/cli-node-linux-x64/bin/opencode2-node regular file byk:byk 755 207830212 packages/cli/dist-v2-pilot-final/cli-node-linux-x64/bin/opencode2-node: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=01ed129fb51ffd798127b17978435ef452e72ad4, for GNU/Linux 3.2.0, with debug_info, not stripped opencode2-node v0.0.0-v2-pilot-202609080301
was compiled against a different Node.js version using NODE_MODULE_VERSION %d. This version of Node.js requires NODE_MODULE_VERSION %d. Please try re-compiling or re-installing "nodeVersion" %ld does not match current Node.js version %d for %s No config found for current Node.js version %d in "configs" for %s https://nodejs.org/download/release/v26.4.0/node-v26.4.0.tar.gz https://nodejs.org/download/release/v26.4.0/node-v26.4.0-headers.tar.gz print Node.js version Write Node.js version %s Failed to load the startup snapshot because it was built withNode.js version %s and the current Node.js version is %s.
<path>/home/byk/.local/share/opencode-v2-pilot/supervisor/go.mod</path> <type>file</type> <content> 1: module opencode-pty-supervisor 2: 3: go 1.22 4: 5: require ( 6: github.com/coreos/go-systemd/v22 v22.5.0 7: github.com/godbus/dbus/v5 v5.1.0 8: golang.org/x/sys v0.20.0 9: ) (End of file - total 9 lines) </content>
drwxr-xr-x 15 byk byk 12288 Sep 8 08:24 /tmp/opencode ff03df72fc6a401e8070db776ceba524e9111d9d907c6f4939244354564a86f2 /tmp/opencode/pty-final-review-a/opencode-pty-supervisor d833c859476f021565e8f425e6ee51353909060fa5f64ce629fb07d3411987dd /tmp/opencode/pty-final-review-a/opencode-pty-launcher fb8739d98ff7882782005e04ef731b6120e8daf0719e606362a1fe620adc2cde /tmp/opencode/pty-final-review-a/opencode-pty-client ff03df72fc6a401e8070db776ceba524e9111d9d907c6f4939244354564a86f2 /tmp/opencode/pty-final-review-b/opencode-pty-supervisor d833c859476f021565e8f425e6ee51353909060fa5f64ce629fb07d3411987dd /tmp/opencode/pty-final-review-b/opencode-pty-launcher fb8739d98ff7882782005e04ef731b6120e8daf0719e606362a1fe620adc2cde /tmp/opencode/pty-final-review-b/opencode-pty-client
Found 51 matches /home/byk/Code/opencode-v2-pilot/bun.lock: Line 21: "@typescript/native-preview": "catalog:", Line 25: "oxlint-tsgolint": "0.21.0", Line 50: "@typescript/native-preview": "catalog:", Line 102: "@typescript/native-preview": "catalog:", Line 164: "@typescript/native-preview": "catalog:", Line 186: "@typescript/native-preview": "catalog:", Line 211: "@typescript/native-preview": "catalog:", Line 244: "@typescript/native-preview": "catalog:", Line 271: "@typescript/native-preview": "catalog:", Line 290: "@typescript/native-preview": "catalog:", Line 333: "@typescript/native-preview": "catalog:", Line 438: "@typescript/native-preview": "catalog:", Line 493: "@typescript/native-preview": "catalog:", Line 526: "@typescript/native-preview": "catalog:", Line 544: "@typescript/native-preview": "catalog:", Line ...
No files found
No files found
? opencode-pty-supervisor/cmd/supervisor [no test files] ok opencode-pty-supervisor/cmd/client (cached) ok opencode-pty-supervisor/cmd/launcher (cached) ok opencode-pty-supervisor/internal/protocol (cached) ok opencode-pty-supervisor/internal/supervisor (cached) ok opencode-pty-supervisor/cmd/client (cached) ok opencode-pty-supervisor/cmd/launcher (cached) ? opencode-pty-supervisor/cmd/supervisor [no test files] ok opencode-pty-supervisor/internal/protocol (cached) ok opencode-pty-supervisor/internal/supervisor 5.014s
$ tsgo --noEmit
$ tsgo -b tsconfig.json tsconfig.tests.json
(no output)
/home/byk/Code/opencode-v2-pilot/packages/core/test/persistent-pty-daemon.test.ts /home/byk/Code/opencode-v2-pilot/packages/core/test/pty/pty-windows.test.ts /home/byk/Code/opencode-v2-pilot/packages/core/test/pty/pty-session.test.ts
Found 7 matches
/home/byk/Code/opencode-v2-pilot/packages/core/test/pty/pty-session.test.ts:
Line 12: import { testEffect } from "../lib/effect"
Line 20: const it = testEffect(
Line 23: const ptyTest = process.platform === "win32" ? it.live.skip : it.live
Line 89: describe("pty", () => {
Line 90: it.live("returns typed not found errors for missing sessions", () =>
Line 204: const configuredIt = testEffect(
Line 209: describe("pty create defaults", () => {
bun test v1.3.14 (0d9b296a)
test/plugin.test.ts:
[00:02:00.000] INFO (#7689): credential updated {
credentialID: "cred_080238920001XYTNDJjoFtMF8B",
integrationID: "refresh-fixture",
valueChanged: true,
labelChanged: false,
}
31 pass
2 skip
0 fail
107 expect() calls
Ran 33 tests across 4 files. [2.74s]
{"tools":["pty_spawn","pty_write","pty_read","pty_list","pty_kill"],"permissions":true,"ownership":true,"interactive":true,"notification":true,"timeout":true,"supervisorStop":true,"failClosedActivation":true,"sessionDeletion":true,"inflightDeletion":true,"atomicReservations":true,"argvBounds":true,"utf8Bytes":true,"linePaging":true,"preListenerOutputBound":true,"cleanup":true}
{"tools":["pty_spawn","pty_write","pty_read","pty_list","pty_kill"],"permissions":true,"ownership":true,"interactive":true,"notification":true,"timeout":true,"supervisorStop":true,"failClosedActivation":true,"sessionDeletion":true,"inflightDeletion":true,"atomicReservations":true,"argvBounds":true,"utf8Bytes":true,"linePaging":true,"preListenerOutputBound":true,"cleanup":true}
{"tools":["pty_spawn","pty_write","pty_read","pty_list","pty_kill"],"permissions":true,"ownership":true,"interactive":true,"notification":true,"timeout":true,"supervisorStop":true,"failClosedActivation":true,"sessionDeletion":true,"inflight...
opencode-pty-supervisor.service: Command /usr/local/libexec/opencode-pty-supervisor is not executable: No such file or directory opencode-v2.service: Command /usr/local/libexec/opencode-pty-verify-readiness is not executable: No such file or directory
A fail-open marker parsing bug is now confirmed by inspection: after four valid newline-terminated records, read returns nonzero for trailing bytes without a final newline, so lines 20-22 accept that extra data. This violates the stated exact four-line format and is a source-level MUST-FIX; I will still finish the remaining checks to rule out additional blockers.
verifier-equivalent trailing-byte status=0
The candidate fails the same-UID integrity model more directly than the Node-version question: ExecStart and both auto-loaded PTY plugins live beneath user-writable byk directories, while the readiness verifier hashes only the three Go binaries. A same-UID process can replace the SEA executable or plugin, signal the user-owned MainPID, and let Restart=always launch altered MainPID code that still satisfies supervisor authentication; neither the marker nor the documented install flow detects this.
Your final security review returned empty. Resume the same READ-ONLY review against the unchanged source manifest fff146df36754bc59d473a070985c4310cb57bdad64473ec7f68b5be5014286f and unchanged artifacts: supervisor ff03df72fc6a401e8070db776ceba524e9111d9d907c6f4939244354564a86f2, launcher d833c859476f021565e8f425e6ee51353909060fa5f64ce629fb07d3411987dd, client fb8739d98ff7882782005e04ef731b6120e8daf0719e606362a1fe620adc2cde. You must return substantive current file:line evidence for every requested prior blocker and full threat-model area, or name the exact tool/error that blocks review. Verify the manifest and hashes first. Classify every finding PASS, CONCERN, or MUST-FIX. Distinguish source approval from pending root-host acceptance. Never edit files, install/start/stop services, or perform privileged operations. End exactly MERGE or DO-NOT-MERGE.
fff146df36754bc59d473a070985c4310cb57bdad64473ec7f68b5be5014286f ff03df72fc6a401e8070db776ceba524e9111d9d907c6f4939244354564a86f2 bin/opencode-pty-supervisor d833c859476f021565e8f425e6ee51353909060fa5f64ce629fb07d3411987dd bin/opencode-pty-launcher fb8739d98ff7882782005e04ef731b6120e8daf0719e606362a1fe620adc2cde bin/opencode-pty-client
<path>/home/byk/Code/opencode-v2-pilot/packages/core/src/plugin/host.ts</path>
<type>file</type>
<content>
374: mcp.transform((editor) => {
375: callback({
376: list: () => editor.list().map(([name, config]) => [name, mutable(config)]),
377: get: (name) => mutable(editor.get(name)),
378: set: (name, config) => editor.set(name, Schema.decodeUnknownSync(ServerConfig)(config)),
379: update: editor.update,
380: remove: editor.remove,
381: })
382: }),
383: },
384: permission: {
385: hook: (name, callback) => hooks.register("permission", name, callback),
386: assert: permission.assert,
387: list: (input) => permission.forSession(input.sessionID),
388: get: (input) =>
389: permission
390: .get(input.requestID)
391: .pipe(
392: Effect.flatMap((request) =>
393: request?.sessionID === input.sessionID
394: ...
<path>/home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/adapter.ts</path>
<type>file</type>
<content>
426: resolve: (connection) => Effect.runPromiseWith(context)(host.integration.connection.resolve(connection)),
427: },
428: },
429: mcp: {
430: list: adaptApiMethod(McpEndpoints["mcp.list"], host.mcp.list),
431: transform: transform(host.mcp),
432: reload: () => run(host.mcp.reload()),
433: },
434: permission: {
435: hook: (name, callback) =>
436: register(host.permission.hook(name, (event) => Effect.promise(() => Promise.resolve(callback(event))))),
437: assert: (input) =>
438: run(
439: host.permission.assert(input).pipe(
440: Effect.catch((error) => Effect.die(new TypedFailure(error))),
441: ),
442: ),
443: list: ...
<path>/home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/adapter.ts</path>
<type>file</type>
<content>
600: (cleanup) => (cleanup ? Effect.promise(() => Promise.resolve(cleanup())) : Effect.void),
601: )
602: }),
603: })
604: }
605:
606: function attempt<A>(evaluate: (signal: AbortSignal) => PromiseLike<A>) {
607: return Effect.tryPromise({ try: evaluate, catch: (cause) => cause })
608: }
609:
610: type RuntimeSchema = Schema.Codec<unknown, unknown>
611:
612: const executePromiseTool = (tool: Info, input: any, context: Tool.Context) =>
613: Effect.tryPromise({
614: try: () =>
615: tool.execute(input, {
616: ...context,
617: progress: (update) => Effect.runPromise(context.progress(update)),
618: }),
619: catch: (error) => error,
620: }).pipe(
621: Effect.catch((error) =>
622: error instanceof TypedFailure
623: ? Effect.fail(
624: new Tool.Error({
625: ...
uid=1000(byk) gid=1000(byk) groups=1000(byk),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),101(lxd),111(docker) adm:x:4:syslog,byk
(no output)
774-.sp 775-If the 776-\fIUser=\fR 777-setting is used the supplementary group list is initialized from the specified user\*(Aqs default group list, as defined in the system\*(Aqs user and group database\&. Additional groups may be configured through the 778:\fISupplementaryGroups=\fR 779-setting (see below)\&. 780-.RE 781-.PP 782-\fIDynamicUser=\fR 783-.RS 4 784-Takes a boolean parameter\&. If set, a UNIX user and group pair is allocated dynamically when the unit is started, and released as soon as it is stopped\&. The user and group will not be added to 785-/etc/passwd 786-or 787-/etc/group, but are managed transiently during runtime\&. The 788-\fBnss-systemd\fR(8) 789-glibc NSS module provides integration of these dynamic users/groups into the system\*(Aqs user and group databases\&. The user and group name to use may be configured via 790-\fIUser=\fR -- 828-.sp 829-Added in version 232\&. 830-.RE 831-.PP 832:\fISupplementaryGroups=\fR 833-.RS 4 834-Sets the supplementary Unix ...
/usr/local/libexec/opencode-pty-supervisor absent /usr/local/libexec/opencode-pty-launcher absent /usr/local/libexec/opencode-pty-client absent /usr/local/libexec/opencode-pty-verify-readiness absent /etc/opencode/pty-supervisor-verified absent ptrace_scope=1 6.8.0-117-generic
[
{
"content": "Inventory and hash exact supervisor, plugin, config, unit, CUTOVER, and PTY test scope",
"status": "completed",
"priority": "high"
},
{
"content": "Trace every prior blocker and the full threat model through current source and tests",
"status": "completed",
"priority": "high"
},
{
"content": "Run unprivileged tests, canonical typecheck, and reproducible artifact builds in /tmp/opencode",
"status": "completed",
"priority": "high"
},
{
"content": "Deliver evidence-backed PASS/CONCERN/MUST-FIX verdict separating source approval from host acceptance",
"status": "in_progress",
"priority": "high"
}
]
[
{
"content": "Inventory and hash exact supervisor, plugin, config, unit, CUTOVER, and PTY test scope",
"status": "completed",
"priority": "high"
},
{
"content": "Trace every prior blocker and the full threat model through current source and tests",
"status": "completed",
"priority": "high"
},
{
"content": "Run unprivileged tests, canonical typecheck, and reproducible artifact builds in /tmp/opencode",
"status": "completed",
"priority": "high"
},
{
"content": "Deliver evidence-backed PASS/CONCERN/MUST-FIX verdict separating source approval from host acceptance",
"status": "completed",
"priority": "high"
}
]
Verdict Source approval and deployment acceptance both fail. Three source/integrity blockers remain.
MUST-FIX
Supplementary groups are not cleared.
User=byk, Group=byk, and an empty SupplementaryGroups property at supervisor/internal/supervisor/systemd.go:459-462.SupplementaryGroups= only clears additional unit assignments. It never overrides database groups.id byk returns adm, sudo, lxd, and docker, among others.supervisor/PROTOCOL.md:50 and the required empty-group assertion at supervisor/ROOT-ACCEPTANCE.md:25.InaccessiblePaths blocks known Docker sockets at systemd.go:495, but retaining lxd or another privileged group remains unsafe and violates the stated invariant.The readiness verifier accepts trailing data without a newline.
supervisor/verify-readiness:15-19.verify-readiness:20-22 assumes read succeeds whenever bytes remain.read returns nonzero when EOF follows a non-newline-terminated value. Therefore trailing-without-newline is accepted after the four valid lines.0.CUTOVER.md:20, ROOT-ACCEPTANCE.md:43, and the verifier’s own error text.internal/supervisor/systemd_test.go:176-198 only checks source-digest inclusion and shell syntax. It has no adversarial marker-format test.The marker does not bind the complete executable security boundary.
packages/plugin/src, local plugins, selected config/unit files, and lockfiles at supervisor/review-source-hash:7-21. ...* 🟡 (08:26) Candidate manifest listed SHA-256 bindings: `verify-readiness`=`8f7a60bdd3391142028ffd8fd105a6807c7cdf1cdd7447fb347bcf3c1871dbda`; `review-source-hash`=`f231f9f8c57fbcadda3a32c7559cd3e45421647312269e04a6798187566584f6`; `ROOT-ACCEPTANCE.md`=`066ad0a2171eb2591be8cf5465cb7caeadb5c6ab90ddd662d76c3e240e185e58`; `PROTOCOL.md`=`0066936168c35d2e0162f182d76feaa37c42b1499feb061972cb9343b8c7f2…
Date: Sep 8, 2026 * 🟡 (08:25) Reviewed `/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/supervisor/auth_test.go`, a 96-line Go test file in package `supervisor`. It defines `authenticationManager` with a configurable `clientIdentity`; `ClientState` returns that identity, while `Start`, `StopAndWait`, `Wait`, `CleanupOrphans`, and `Close` are no-op test implementations. * 🟡 (08:25) …
* 🟡 (08:21) Reviewed `packages/core/src/permission.ts` lines 221–252: `Permission.assert` evaluates input, returns `BlockedError` for `"deny"` with `rules`, `permission`, `resources`, and `reason`; returns immediately for `"allow"`; otherwise creates a pending request inside `Effect.uninterruptibleMask`, restores interruptibility only around `Deferred.await(item.deferred)`, tunnels `Permission.D…
Date: Sep 8, 2026 * 🔴 (08:20) User requires `bun typecheck` to be run from package directories such as `packages/core`; never run `tsc` directly. * 🔴 (08:20) User requires runtime dependencies to flow from Schema to Core and Protocol, then from Core and Protocol to Server. Client runtime code may depend on Schema and Protocol, but never Core or Server; `sdk` composes Client, Core, and Server. *…
Date: Sep 8, 2026 * 🟡 (08:19) Reviewed `/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/supervisor/server_test.go` (787 lines). `TestReceiveStartWithDirectoryDescriptor` transfers one cwd descriptor via `SCM_RIGHTS`, requires `FD_CLOEXEC`, and verifies command `printf` with argument `ok`; `TestReceiveStartRejectsMetadataMismatch` rejects supplied device/inode values `1`/`2` that do …
Date: Sep 8, 2026 * 🔴 (08:18) User stated the PTY client helper never initiates a socket connection, resolves a caller path, or opens an application-selected path. * 🔴 (08:18) User stated source behavior never proves that all other Node child processes inherit neither the connected socket descriptor nor the approved-directory descriptor; exact Node 26.4 SEA descriptor inheritance and same-UID d…
Date: Sep 8, 2026 * 🟡 (08:17) Reviewed `/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/supervisor/auth.go` (108 lines). `authenticate()` obtains both `SO_PEERCRED` and `SO_PEERPIDFD`, validates the peer PID/UID/GID, queries `manager.ClientState(ctx)`, and requires the peer PID to equal the service `MainPID` while `ActiveState=="active"`, `SubState=="running"`, `ControlGroup==expect…
Date: Sep 8, 2026 * 🟢 (08:16) A file-search tool returned `No files found`. * 🟡 (08:16) Assistant confirmed the source manifest and all three artifact hashes matched exactly, and classified the host’s Node `v24.16.0` versus required Node `26.4` as a deployment-acceptance blocker rather than a source defect. * 🟡 (08:16) Reviewed `/home/byk/.local/share/opencode-v2-pilot/supervisor/internal/supe…
Date: Sep 8, 2026 * 🟡 (08:13) User requested a final, substantive, independent, READ-ONLY security review of the exact current source and artifacts under `/home/byk/.local/share/opencode-v2-pilot/supervisor`; plugin files `/home/byk/.local/share/opencode-v2-pilot/config/opencode/plugins/pty.ts` and `/home/byk/.local/share/opencode-v2-pilot/config/opencode/plugins/pty-transport.ts`; canonical con…