Skip to content

Commit c2a5438

Browse files
committed
initial public release
0 parents  commit c2a5438

24 files changed

Lines changed: 3598 additions & 0 deletions

.dockerignore

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.env
2+
.git
3+
.venv
4+
venv
5+
__pycache__
6+
**/__pycache__
7+
**/*.pyc
8+
.pytest_cache
9+
.mypy_cache
10+
.ruff_cache
11+
data
12+
.discovery
13+
*.log
14+
logs
15+
tmp
16+
temp
17+
.DS_Store
18+
.idea
19+
.vscode
20+
auth.json
21+
codex-home
22+
.codex

.env.example

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copy to .env. Keep actual secrets in ignored files under data/secrets/.
2+
# Do not commit .env or data/.
3+
4+
# Optional: set only when using docker-compose.image.yml to pull a published
5+
# image instead of building locally. Use a specific versioned tag, not latest.
6+
# CODEX_CLI_PROVIDER_IMAGE=registry.example.com/your-org/codex-cli-provider:codex-cli-provider-0.1.2
7+
8+
PROXY_API_KEY_FILE=data/secrets/proxy_api_key
9+
10+
CODEX_HOME=/root/.codex
11+
CODEX_WORK_DIR=/workspace
12+
CODEX_BIN=codex
13+
CODEX_UPSTREAM_MODEL=
14+
CODEX_REQUEST_TIMEOUT_SECONDS=180
15+
DASHBOARD_ENABLED=true
16+
17+
# Defaults are conservative. For large LLM Wiki lint prompts, raise these up to
18+
# MAX_REQUEST_BODY_BYTES=2000000 and MAX_TOTAL_TEXT_CHARS=500000.
19+
MAX_REQUEST_BODY_BYTES=262144
20+
MAX_MESSAGES=32
21+
MAX_TOTAL_TEXT_CHARS=80000
22+
23+
# Local admission queue for short bursts while preserving one active Codex run.
24+
# 0 fails fast with wrapper_busy 429. Values above 0 wait up to that many
25+
# seconds for the active run to finish. The app clamps this to 0-5 seconds.
26+
QUEUE_WAIT_SECONDS=0
27+
CORS_ALLOWED_ORIGINS=
28+
LOG_LEVEL=INFO

.github/dependabot.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: github-actions
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
day: monday
8+
time: "10:00"
9+
open-pull-requests-limit: 5
10+
11+
- package-ecosystem: pip
12+
directory: /
13+
schedule:
14+
interval: weekly
15+
day: monday
16+
time: "10:30"
17+
open-pull-requests-limit: 5

.github/workflows/ci.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: ci
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
- master
9+
10+
permissions:
11+
contents: read
12+
13+
concurrency:
14+
group: ci-${{ github.workflow }}-${{ github.ref }}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
test-build:
19+
runs-on: ubuntu-latest
20+
timeout-minutes: 20
21+
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
25+
26+
- name: Set up Python
27+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
28+
with:
29+
python-version: "3.12"
30+
cache: pip
31+
32+
- name: Install dependencies
33+
run: |
34+
pip install --requirement requirements.txt
35+
36+
- name: Unit tests
37+
run: python -m pytest -q
38+
39+
- name: Syntax checks
40+
run: python -m py_compile src/server.py scripts/check_compose_security.py scripts/check_repo_hygiene.py tests/test_server.py
41+
42+
- name: Prepare throwaway local config
43+
run: |
44+
cp .env.example .env
45+
mkdir -p data/secrets data/codex-home data/codex-work
46+
python - <<'PY'
47+
import pathlib
48+
import secrets
49+
50+
pathlib.Path("data/secrets/proxy_api_key").write_text(secrets.token_urlsafe(48) + "\n", encoding="utf-8")
51+
PY
52+
chmod 600 .env
53+
chmod 644 data/secrets/proxy_api_key
54+
chmod 700 data/secrets data/codex-home data/codex-work
55+
56+
- name: Repo hygiene checks
57+
run: python scripts/check_repo_hygiene.py
58+
59+
- name: Compose render
60+
run: docker compose config
61+
62+
- name: Compose security checks
63+
run: python scripts/check_compose_security.py
64+
65+
- name: Docker build
66+
run: docker compose build

.github/workflows/release.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
image_tag:
7+
description: "Image tag to publish, for example v0.1.0 or test"
8+
required: true
9+
type: string
10+
push:
11+
tags:
12+
- "v*.*.*"
13+
14+
permissions:
15+
contents: read
16+
packages: write
17+
18+
concurrency:
19+
group: release-${{ github.ref }}
20+
cancel-in-progress: false
21+
22+
jobs:
23+
publish-image:
24+
runs-on: ubuntu-latest
25+
timeout-minutes: 30
26+
27+
steps:
28+
- name: Checkout
29+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
30+
31+
- name: Set up Docker Buildx
32+
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
33+
34+
- name: Log in to GHCR
35+
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
36+
with:
37+
registry: ghcr.io
38+
username: ${{ github.actor }}
39+
password: ${{ secrets.GITHUB_TOKEN }}
40+
41+
- name: Docker metadata
42+
id: meta
43+
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5
44+
with:
45+
images: ghcr.io/${{ github.repository }}
46+
tags: |
47+
type=raw,value=${{ inputs.image_tag }},enable=${{ github.event_name == 'workflow_dispatch' }}
48+
type=ref,event=tag
49+
50+
- name: Build and publish image
51+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
52+
with:
53+
context: .
54+
file: Dockerfile
55+
platforms: linux/amd64,linux/arm64
56+
push: true
57+
tags: ${{ steps.meta.outputs.tags }}
58+
labels: ${{ steps.meta.outputs.labels }}

.github/workflows/security.yml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
name: security
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
- master
9+
schedule:
10+
- cron: "27 9 * * 1"
11+
12+
permissions:
13+
contents: read
14+
security-events: write
15+
16+
concurrency:
17+
group: security-${{ github.workflow }}-${{ github.ref }}
18+
cancel-in-progress: true
19+
20+
jobs:
21+
codeql:
22+
runs-on: ubuntu-latest
23+
timeout-minutes: 20
24+
permissions:
25+
contents: read
26+
security-events: write
27+
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
31+
32+
- name: Initialize CodeQL
33+
uses: github/codeql-action/init@dd903d2e4f5405488e5ef1422510ee31c8b32357 # v3
34+
with:
35+
languages: python
36+
37+
- name: Perform CodeQL analysis
38+
uses: github/codeql-action/analyze@dd903d2e4f5405488e5ef1422510ee31c8b32357 # v3
39+
40+
dependency-audit:
41+
runs-on: ubuntu-latest
42+
timeout-minutes: 15
43+
permissions:
44+
contents: read
45+
46+
steps:
47+
- name: Checkout
48+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
49+
50+
- name: Set up Python
51+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
52+
with:
53+
python-version: "3.12"
54+
cache: pip
55+
56+
- name: Run pip-audit
57+
run: |
58+
python -m pip install pip-audit==2.10.1
59+
pip-audit --requirement requirements.txt
60+
61+
container-scan:
62+
runs-on: ubuntu-latest
63+
timeout-minutes: 25
64+
permissions:
65+
contents: read
66+
67+
steps:
68+
- name: Checkout
69+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
70+
71+
- name: Prepare throwaway local config
72+
run: |
73+
cp .env.example .env
74+
mkdir -p data/secrets data/codex-home data/codex-work
75+
python - <<'PY'
76+
import pathlib
77+
import secrets
78+
79+
pathlib.Path("data/secrets/proxy_api_key").write_text(secrets.token_urlsafe(48) + "\n", encoding="utf-8")
80+
PY
81+
chmod 600 .env
82+
chmod 644 data/secrets/proxy_api_key
83+
chmod 700 data/secrets data/codex-home data/codex-work
84+
85+
- name: Build local image
86+
run: docker compose build
87+
88+
- name: Trivy image scan
89+
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
90+
with:
91+
image-ref: codex-cli-provider:local
92+
format: table
93+
severity: CRITICAL,HIGH
94+
exit-code: "1"
95+
ignore-unfixed: true

.gitignore

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
.env
2+
.venv/
3+
venv/
4+
__pycache__/
5+
*.py[cod]
6+
.pytest_cache/
7+
.mypy_cache/
8+
.ruff_cache/
9+
10+
data/
11+
.discovery/
12+
*.log
13+
logs/
14+
tmp/
15+
temp/
16+
17+
.DS_Store
18+
.idea/
19+
.vscode/
20+
*.swp
21+
*~
22+
23+
auth.json
24+
codex-home/
25+
.codex/
26+
sessions/
27+
history.jsonl

AGENTS.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# AGENTS.md
2+
3+
Project notes for future Codex/agent sessions.
4+
5+
## Published Images
6+
7+
Public users should build locally by default:
8+
9+
```bash
10+
docker compose up --build -d
11+
```
12+
13+
Use the image-only Compose file only when pulling a published image. Do not use
14+
`latest`; tags should include the image name and version, for example
15+
`codex-cli-provider-0.1.2`.
16+
17+
```bash
18+
CODEX_CLI_PROVIDER_IMAGE=registry.example.com/your-org/codex-cli-provider:codex-cli-provider-0.1.2 \
19+
docker compose -f docker-compose.image.yml up -d
20+
```
21+
22+
## Auth Boundaries
23+
24+
Do not bake credentials into the image or Compose files.
25+
26+
- Docker Hub auth belongs in local Docker credential storage via `docker login`.
27+
- The wrapper bearer token belongs in `data/secrets/proxy_api_key`.
28+
- Codex/ChatGPT auth belongs in the dedicated bind-mounted `data/codex-home`.
29+
- Do not use or add `OPENAI_API_KEY`, `CODEX_API_KEY`, or
30+
`CODEX_ACCESS_TOKEN` for this project.
31+
32+
Codex login is completed inside the running container so credentials are written
33+
to the mounted `/root/.codex` backed by `data/codex-home`:
34+
35+
```bash
36+
docker exec -it codex-cli-provider \
37+
codex login --device-auth \
38+
-c forced_login_method='"chatgpt"' \
39+
-c cli_auth_credentials_store='"file"'
40+
```
41+
42+
## Local Development
43+
44+
Use the default Compose file when building locally:
45+
46+
```bash
47+
docker compose up --build -d
48+
```
49+
50+
Use `docker-compose.image.yml` only when pulling a published image.
51+
52+
## Verification
53+
54+
Before handing off changes, run:
55+
56+
```bash
57+
python3 scripts/check_repo_hygiene.py
58+
python3 scripts/check_compose_security.py
59+
COMPOSE_FILE=docker-compose.image.yml CODEX_CLI_PROVIDER_IMAGE=registry.example.com/your-org/codex-cli-provider:codex-cli-provider-0.1.2 python3 scripts/check_compose_security.py
60+
PYTHONPATH=. .venv/bin/pytest -q
61+
```
62+
63+
The test suite expects the repo root on `PYTHONPATH`, matching the container's
64+
`PYTHONPATH=/app` setting.
65+
66+
## Security Notes
67+
68+
The Dockerfile currently copies only `requirements.txt` and `src/`. Keep it that
69+
way unless there is a specific reason to widen the build context. `.dockerignore`
70+
excludes `.env`, `data/`, Codex auth files, virtualenvs, logs, and other local
71+
state that must not be published in images.

0 commit comments

Comments
 (0)