@pushary/codex-app-server 0.0.0-stage → 0.1.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.
@@ -0,0 +1,84 @@
1
+ # Compatibility evidence
2
+
3
+ Status: experimental 0.1.0 release; certified only for Codex 0.160.1.
4
+
5
+ | Boundary | Evidence |
6
+ | --- | --- |
7
+ | Codex | npm `@openai/codex@0.160.1`; generated schemas and SHA-256 provenance under `test/fixtures/0.160.1` |
8
+ | Transport | newline JSON over stdio; 1 MiB frame cap, bounded FIFO, separate host RPC IDs |
9
+ | Thread policy | real initialize/start response; user reviewer and read-only sandbox |
10
+ | Command | real `exec_command` request, accept/deny, absent side effect before approval, file written only after accept |
11
+ | File | real patch interception through `exec_command`, full cached patch approval, accept/deny filesystem evidence |
12
+ | Questions | real built-in tool adds `isOther:true`; native fallback interrupts the turn. Restricted `isOther:false` subset tested with synthetic protocol messages only |
13
+ | Partner | production Partner service and an enrolled physical iPhone; command approve/deny/expiry, full patch approval, privacy refusal and customer-bound recipient enforcement |
14
+ | Runtime | Node 22 on macOS and Debian Linux verified from standalone installs; Node 24 on macOS and Ubuntu also verified |
15
+ | Packaging | ESM/CJS packed-consumer smoke with published SDK 2.3.0; standalone lock includes registry URL and integrity |
16
+
17
+ Regenerate the schemas with `npm run capture:protocol`. They include experimental fields because the supported live messages advertise `availableDecisions`; omitting `--experimental` hides that field from generated schema output. The adapter still refuses unrecognized permission-bearing fields.
18
+
19
+ A local command uses `environmentId:"local"` and may offer an exec-policy amendment. These are validated; the adapter can answer only the request itself. It never returns `acceptForSession` or any amendment. If the menu omits `decline`, a negative phone answer uses `cancel`.
20
+
21
+ The mock Responses service scripts the model's tool call but does not replace Codex: Codex validates the tool, requests approval, waits, executes/refuses the action, and emits the turn outcome. This proves the local protocol/execution seam, not mobile delivery or provider behavior. Linux sandbox behavior is checked by the monorepo release-candidate job and must be green before release.
22
+
23
+ Registry installation is a post-publication check. Local packed-consumer tests do not prove that the npm upload succeeded.
24
+
25
+ ## Local verification, 2026-10-07
26
+
27
+ On Node 24.3.0/macOS: 106 adapter unit/race tests, 8 real-binary scenarios, 7 host lifecycle tests,
28
+ 105 SDK tests, 33 Claude adapter regressions, and 20 OpenAI Agents adapter/hosted
29
+ regressions passed. The monorepo typecheck passed all 21 tasks. The mandatory
30
+ commit gate passed all checks. Packed ESM/CJS imports and the standalone mirror
31
+ build/tests/simulated example passed using the locally packed SDK candidate.
32
+
33
+ The initial sandboxed gate could not bind its localhost fixture; the full gate
34
+ was rerun with localhost access and passed. No test used personal Codex config,
35
+ a production Partner credential, or a real model endpoint.
36
+
37
+ ## Standalone verification, 2026-10-08
38
+
39
+ The standalone lock now resolves published SDK 2.3.0 with its npm registry URL
40
+ and integrity. A clean install on Node 22.23.3/macOS passed typecheck, all 106
41
+ unit/race tests and all 15 pinned-binary/host lifecycle checks. The packed
42
+ adapter passed ESM/CJS consumer smoke with the registry SDK on Node 22.
43
+
44
+ A fresh standalone install in the official `node:22-bookworm` Linux container
45
+ also passed typecheck, all 106 unit/race tests and all 15 pinned-binary/host
46
+ checks with the registry SDK. Its temporary workspace was isolated from host
47
+ configuration and the container was removed after completion.
48
+
49
+ The [Ubuntu/Node 24 release-candidate job](https://github.com/aadilghani1/pushary/actions/runs/37647923638/job/112883426512)
50
+ passed the same 106 unit/race tests and 15 pinned-binary/host checks on October 7.
51
+ Its adapter source, tests, examples and package manifest match this revision.
52
+ The job built and packed the candidate without publishing it.
53
+
54
+ The mirror repository and npm package still returned 404 during this check.
55
+ No public repository, npm package, or trusted publisher was created, and the
56
+ release and provisioning remain blocked pending certification.
57
+
58
+
59
+ ## Physical-phone certification, 2026-10-08
60
+
61
+ A dedicated Partner test customer was enrolled on a physical iPhone. The real
62
+ Codex 0.160.1 binary ran with isolated temporary configuration and workspace,
63
+ a scripted loopback Responses service and the production Partner API.
64
+
65
+ - Phone approval resumed the waiting command and wrote exactly the expected file.
66
+ - Phone denial interrupted the turn and wrote no file.
67
+ - An unanswered decision expired, interrupted the turn and wrote no file.
68
+ - A complete file patch reached the phone and approval applied its exact Unicode
69
+ contents. The customer confirmed all beginning/end markers and lines were visible.
70
+ - Privacy refusal created no Partner decision and executed nothing.
71
+ - A customer-bound key overrode a different requested external ID; the resulting
72
+ decision belonged to the enrolled customer. Enrollment, key issuance and submitting
73
+ a customer answer with that key each returned HTTP 403.
74
+
75
+ No command or patch executed before an answer. A mistakenly approved denial test
76
+ executed as approved; it was repeated with a denial and passed. This verifies the
77
+ answer received, not an inferred user intention. One initial unanswered approval
78
+ attempt expired without execution and was then repeated successfully.
79
+
80
+ Known presentation limitation: patch newlines display as literal `\u{a}` text.
81
+ All contents are present, but multiline review is less readable. The display fix
82
+ is deferred; this release preserves the certified presentation. Native Codex
83
+ questions, restart recovery and exactly-once execution remain unsupported as
84
+ specified above. No real model-provider behavior was certified by this fixture.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Pushary
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,8 @@
1
+ Pushary Codex app-server adapter: MIT (see LICENSE).
2
+
3
+ Generated test schema fixtures are derived without manual edits from OpenAI Codex
4
+ 0.160.1, https://github.com/openai/codex/tree/rust-v0.160.1.
5
+ Copyright OpenAI. Licensed under the Apache License, Version 2.0.
6
+ The source checkout includes the complete upstream license at
7
+ test/fixtures/0.160.1/LICENSE. Published npm artifacts contain no schema fixtures.
8
+ The upstream CLI is a development dependency, not bundled in this package.
package/README.md CHANGED
@@ -1,3 +1,97 @@
1
- # Temporary Holding Version
1
+ # @pushary/codex-app-server
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Route live Codex app-server command and file approvals to an enrolled Pushary Partner customer. The host keeps control of Codex authentication, process lifetime, native UI, and response delivery. This MIT package uses only the public `@pushary/server` SDK.
4
+
5
+ Experimental release: pinned to **Codex 0.160.1**, Node 22/24, and **@pushary/server >=2.3.0**. See [compatibility and verification](COMPATIBILITY.md).
6
+
7
+ ## Install and enroll
8
+
9
+ ```sh
10
+ npm install @pushary/codex-app-server
11
+ ```
12
+
13
+ Install Codex separately if your host launches it. The adapter never installs or starts a Codex process automatically.
14
+
15
+ ```ts
16
+ import { connect, createPusharyCodexHandler } from '@pushary/codex-app-server'
17
+
18
+ const enrollment = await connect({
19
+ apiKey: partnerBackendKey,
20
+ }, authenticatedCustomerId)
21
+ ```
22
+
23
+ Use a full-access Partner backend key for enrollment and issuing customer-bound keys. Agent and customer-bound keys cannot enroll users.
24
+
25
+ Show the returned enrollment link inside your authenticated customer flow. The customer must enroll before receiving decisions. `externalId` comes from your authenticated tenant/customer mapping, never from model output. Keep the Partner key on your host; do not put it into the agent's environment or workspace. Each handler belongs to one tenant, customer and live connection. A full-access key requires your host to enforce tenant isolation; a customer-bound key also enforces the recipient at the API boundary.
26
+
27
+ ## Attach to your transport
28
+
29
+ ```ts
30
+ const approvals = createPusharyCodexHandler({
31
+ apiKey: partnerApiKey,
32
+ tenantId: authenticatedTenantId,
33
+ externalId: authenticatedCustomerId,
34
+ codexVersion: '0.160.1',
35
+ agentName: 'My coding assistant',
36
+ maySendSubject: subject => customerPrivacyPolicy.allows(subject),
37
+ sendResponse: reply => connection.enqueue(reply),
38
+ requestTurnInterrupt: (threadId, turnId) => {
39
+ connection.enqueueRequest('turn/interrupt', { threadId, turnId })
40
+ },
41
+ onEvent: event => audit.write(event),
42
+ })
43
+
44
+ approvals.registerThread(threadStartOrResumeResult)
45
+
46
+ function onServerMessage(message: unknown) {
47
+ const dispatch = approvals.handle(message)
48
+ if (dispatch.kind === 'unhandled') nativeReviewOrRefuse(message)
49
+ if (dispatch.kind === 'invalid') closeConnection()
50
+ }
51
+
52
+ const { cleanupFailures } = await approvals.dispose()
53
+ ```
54
+
55
+ `handle` returns synchronously. Keep reading server messages while a person answers. `claimed` means this handler owns the reply; never open another answer surface for it. `unhandled` delegates the first delivery to native review; later copies of that RPC are suppressed as `claimed` so the host opens only one answer surface. `observed` is a notification. Route host RPC responses separately. `sendResponse` must synchronously accept a frame into a bounded FIFO without calling back into the handler; enqueue failure must throw. An asynchronous writer failure must close the connection and dispose the handler. An interrupt must enter the same queue before the question error response. Close on `reply_failed` or `capacity_exceeded` events.
56
+
57
+ Register the effective **result**, not the parameters you requested. Only `on-request`/`untrusted`, reviewer `user`, and `readOnly`/`workspaceWrite` sandboxes qualify. Do not change permissions in `turn/start`. Settings updates unregister the thread; obtain a fresh idle start/resume result before re-registering. Call `invalidateTurn` before stopping or replacing work; invalidation after acceptance enqueue requests interruption and reports an unknown execution outcome.
58
+
59
+ ## Supported subjects
60
+
61
+ - Full command, working directory and reason. Only one-request `accept`, `decline` or `cancel` is emitted. Known optional exec-policy suggestions do not grant a standing rule. Network, remote environments, stdin, additional permissions and unknown decision options require native handling.
62
+ - Complete file patches cached from `item/started` and `item/fileChange/patchUpdated`. A changed patch invalidates an outstanding approval. Missing or ambiguous patches and `grantRoot` are refused. Every path, operation, rename and diff is presented; nothing is truncated.
63
+ - Optional `experimentalQuestions: true` accepts a bounded protocol subset: 1–3 blocking, nonsecret questions with `isOther:false`. **The built-in Codex 0.160.1 tool always sets `isOther:true`, so its questions need native UI.** The included headless host interrupts them. Synthetic protocol tests cover the smaller subset; they are not evidence of native phone-question support.
64
+
65
+ MCP elicitation, permissions, dynamic tools, account/auth callbacks and legacy v1 approvals remain host responsibilities. The [example host](examples/stdio-host.mjs) has explicit fail-closed fallbacks.
66
+
67
+ ## Lifecycle and privacy
68
+
69
+ The default decision deadline is 300 seconds, configurable from 60 to 600 seconds. It includes create, polling and every question in a batch. Creates use frozen idempotency keys, `wait:false`, and `requireReachable:true`. The key binds the tenant, customer, random connection generation, thread, turn, item, typed RPC ID, callback ID, exact subject and question ordinal. Pending polls are not denials. API errors and malformed answers never grant permission.
70
+
71
+ `maySendSubject` is mandatory and runs before transmission. It receives a copy of the full subject; false or a thrown error leaves the request for native review. Commands and patches can contain secrets. Invisible characters are escaped visibly. Presentations exceeding 8,000 UTF-16 question units or 2,000 context units require native review. Avoid storing raw subjects in your audit log; adapter events contain IDs, digests and reason codes, not command/diff text.
72
+
73
+ Limits per connection: 8 pending requests, 32 registered threads, 128 cached patches/4 MiB, 4,096 combined request, turn and completed-item records. Overflow disposes the connection instead of evicting approval identity. Notification callbacks must be fast; thrown callback errors are logged without exception content.
74
+
75
+ An owned request moves from pending to accepted or closed exactly once. The transition is committed before abort, interruption, or delivery callbacks. Item/turn completion is tracked separately from the reply outcome; cleanup never reopens a request. Deadline refusals use the same transition as other refusals and recheck the context after callbacks.
76
+
77
+ Disposal immediately fences replies, aborts requests and attempts withdrawal of known pending decision IDs for at most five seconds. It is idempotent. A late create is withdrawn only while the cleanup budget remains. An unobservable create outcome or abrupt termination can leave a prompt until its TTL; this is reported explicitly. A late answer can never be reused by a new handler generation.
78
+
79
+ This package supports live sessions only. It does not provide restart recovery, webhook-driven replay, durable ownership, or exactly-once execution. Enqueueing `accept` is not proof of execution: record the later Codex item outcome separately.
80
+
81
+ ## Develop and mirror
82
+
83
+ In the monorepo:
84
+
85
+ ```sh
86
+ bun install --frozen-lockfile
87
+ bun run --cwd packages/server build
88
+ bun run --cwd packages/codex-app-server typecheck
89
+ bun run --cwd packages/codex-app-server test
90
+ node scripts/ci/check-package-artifact.mjs codex-app-server
91
+ ```
92
+
93
+ The conformance suite launches the pinned binary with isolated temporary HOME/CODEX_HOME and a loopback mock Responses/Partner service. It uses no personal login, real model credentials or physical phone. Tests verify actual filesystem effects before and after command/file decisions. They need permission to bind localhost and run the child process.
94
+
95
+ `packages/codex-app-server` is the source of truth. `scripts/lib/mirrors.mjs` maps it to `Pushary/pushary-codex-app-server`, with managed standalone CI/lockfile and release tags, like the other adapters. Never copy private monorepo dependencies into the mirror.
96
+
97
+ SDK 2.3.0 is published and the standalone lock resolves its registry artifact. Physical-phone certification and recipient-isolation checks are recorded in [COMPATIBILITY.md](COMPATIBILITY.md). The provisioned public mirror follows this package, and the shared npm release workflow publishes version bumps. Scheduled protocol drift compares latest generated schemas with the certified fixtures; it never widens the runtime version automatically.