Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ on:

jobs:
test:
name: Test on Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest
name: Test on ${{ matrix.os }} Node.js ${{ matrix.node-version }}
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node-version: [20.x, 22.x]

steps:
Expand Down Expand Up @@ -44,12 +45,32 @@ jobs:
- name: Run type check
run: npm run typecheck

- name: Generate and verify SBOM
run: |
npm run sbom:generate
npm run sbom:verify

- name: Run tests with coverage
run: npm run coverage

- name: Build
run: npm run build

- name: Assert keychain mode storage contract
run: npm run ops:keychain-assert

- name: Seed enterprise health fixture
run: |
node scripts/seed-health-fixture.js

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Enterprise health check
env:
CODEX_MULTI_AUTH_DIR: ${{ github.workspace }}/.tmp/health-fixture
run: npm run ops:health-check -- --require-files

- name: Performance budget check
run: npm run perf:budget-check
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

lint:
name: Lint

Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/recovery-drill.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Recovery Drill

on:
schedule:
- cron: "30 3 1 * *"
workflow_dispatch:

permissions:
contents: read

jobs:
recovery-drill:
name: Monthly Storage Recovery Drill
runs-on: ubuntu-latest
timeout-minutes: 30
Comment thread
ndycode marked this conversation as resolved.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: npm

- name: Install dependencies
run: npm ci

- name: Build
run: npm run build
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Run recovery drill tests
run: |
mkdir -p .tmp
npm run ops:recovery-drill -- --reporter=default --reporter=json --outputFile=.tmp/recovery-drill-vitest.json

Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Run health check snapshot
run: node scripts/enterprise-health-check.js > .tmp/recovery-drill-health.json 2>&1

- name: Upload recovery drill artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: recovery-drill-artifacts
path: |
.tmp/recovery-drill-vitest.json
.tmp/recovery-drill-health.json
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Notify recovery drill failure
if: failure()
env:
RECOVERY_DRILL_WEBHOOK_URL: ${{ secrets.RECOVERY_DRILL_WEBHOOK_URL }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
message="Recovery drill failed. Run: ${RUN_URL}. Artifacts: .tmp/recovery-drill-vitest.json and .tmp/recovery-drill-health.json."
if [[ -n "${RECOVERY_DRILL_WEBHOOK_URL:-}" ]]; then
payload=$(jq -n --arg msg "${message}" '{"text": $msg}')
curl --fail --silent --show-error \
--max-time 30 \
-X POST \
-H "Content-Type: application/json" \
--data "${payload}" \
"${RECOVERY_DRILL_WEBHOOK_URL}"
Comment thread
ndycode marked this conversation as resolved.
else
echo "::warning::${message} Configure secrets.RECOVERY_DRILL_WEBHOOK_URL for push notifications."
fi
59 changes: 59 additions & 0 deletions .github/workflows/release-provenance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Release Publish (Provenance)

on:
workflow_dispatch:
release:
types: [published]

permissions:
contents: read
id-token: write

jobs:
publish:
name: Publish with npm provenance
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
registry-url: https://registry.npmjs.org
cache: npm

- name: Install dependencies
run: npm ci

- name: Validate quality gates
env:
CODEX_MULTI_AUTH_DIR: ${{ github.workspace }}/.tmp/health-fixture
run: |
mkdir -p "${GITHUB_WORKSPACE}/.tmp/health-fixture/logs"
printf '{"version":3,"accounts":[],"activeIndex":0}\n' > "${GITHUB_WORKSPACE}/.tmp/health-fixture/openai-codex-accounts.json"
printf '{"version":1,"pluginConfig":{},"dashboardDisplaySettings":{}}\n' > "${GITHUB_WORKSPACE}/.tmp/health-fixture/settings.json"
printf '{"timestamp":"%s","action":"request.start","outcome":"success"}\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "${GITHUB_WORKSPACE}/.tmp/health-fixture/logs/audit.log"
npm run audit:ci
npm run ops:health-check -- --require-files
npm run perf:budget-check
npm run lint
npm run typecheck
npm run build
npm test
Comment thread
coderabbitai[bot] marked this conversation as resolved.
npm run ops:keychain-assert
npm run sbom:generate
npm run sbom:verify
node scripts/compliance-evidence-bundle.js --profile=quick --out-dir=.tmp/compliance-evidence-release

- name: Upload release evidence bundle
uses: actions/upload-artifact@v4
with:
name: release-evidence-bundle
path: .tmp/compliance-evidence-release

- name: Publish package with provenance
run: npm publish --provenance --access public
Comment thread
coderabbitai[bot] marked this conversation as resolved.
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
48 changes: 48 additions & 0 deletions .github/workflows/retention-maintenance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Retention Maintenance

on:
schedule:
- cron: "15 2 * * 0"
workflow_dispatch:

permissions:
contents: read

jobs:
retention:
name: Weekly Retention Cleanup Drill
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set retention root
run: echo "CODEX_MULTI_AUTH_DIR=${{ runner.temp }}/codex-retention-root" >> "$GITHUB_ENV"

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: npm

- name: Install dependencies
run: npm ci

- name: Prepare retention fixture
run: |
node -e "const fs=require('fs'); const path=require('path'); const root=process.env.CODEX_MULTI_AUTH_DIR; const logs=path.join(root,'logs','codex-plugin'); const cache=path.join(root,'cache'); const recovery=path.join(root,'recovery'); fs.mkdirSync(logs,{recursive:true}); fs.mkdirSync(cache,{recursive:true}); fs.mkdirSync(recovery,{recursive:true}); const oldFile=path.join(logs,'old-audit.log'); const newFile=path.join(cache,'fresh-cache.json'); fs.writeFileSync(oldFile,'old'); fs.writeFileSync(newFile,'new'); const oldTime=new Date(Date.now()-120*24*60*60*1000); fs.utimesSync(oldFile,oldTime,oldTime);"

- name: Run retention cleanup
run: |
mkdir -p .tmp
node scripts/retention-cleanup.js --days=90 > .tmp/retention-report.json

- name: Verify retention fixture cleanup
run: |
node -e "const fs=require('fs'); const path=require('path'); const root=process.env.CODEX_MULTI_AUTH_DIR; const oldFile=path.join(root,'logs','codex-plugin','old-audit.log'); const newFile=path.join(root,'cache','fresh-cache.json'); if(fs.existsSync(oldFile)){console.error('expected old file to be deleted'); process.exit(1);} if(!fs.existsSync(newFile)){console.error('expected fresh file to remain'); process.exit(1);} console.log('retention verification passed');"

- name: Upload retention report
uses: actions/upload-artifact@v4
with:
name: retention-maintenance-report
path: .tmp/retention-report.json
48 changes: 48 additions & 0 deletions .github/workflows/sbom-attestation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: SBOM and Dependency Attestation

on:
pull_request:
branches: [main]
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read
id-token: write
attestations: write

jobs:
sbom:
name: Generate SBOM
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: npm

- name: Install dependencies
run: npm ci

- name: Generate SBOM
run: npm run sbom:generate

- name: Verify SBOM
run: npm run sbom:verify

- name: Upload SBOM artifact
uses: actions/upload-artifact@v4
with:
name: sbom-cyclonedx
path: .tmp/sbom.cdx.json

- name: Attest SBOM provenance
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: actions/attest-build-provenance@v2
with:
subject-path: .tmp/sbom.cdx.json
35 changes: 35 additions & 0 deletions .github/workflows/secret-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Secret Scan

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read
pull-requests: write

jobs:
gitleaks:
name: Gitleaks
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
fetch-depth: 0

- name: Run gitleaks
uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_VERSION: "8.25.0"
GITLEAKS_CONFIG: .gitleaks.toml

- name: Verify secret-scan policy regression
run: bash test/security/secret-scan-regression.test.sh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EXPECTED_GITLEAKS_VERSION: v8.25.0
GITLEAKS_CONFIG: .gitleaks.toml
Comment thread
coderabbitai[bot] marked this conversation as resolved.
19 changes: 19 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
title = "codex-multi-auth gitleaks config"

Comment thread
coderabbitai[bot] marked this conversation as resolved.
[extend]
useDefault = true

[[allowlists]]
description = "Allowlisted fixture/docs synthetic credentials only"
condition = "AND"
paths = [
'''^test[\\/]security[\\/]fixtures[\\/]''',
'''^docs[\\/]releases[\\/]''',
'''^docs[\\/]development[\\/]DEEP_AUDIT_2026-03-01\.md$'''
]
regexes = [
'''fake_refresh_token_[0-9]+''',
'''secret-(access|refresh)-token''',
'''top secret prompt''',
'''sk-test-[A-Za-z0-9]{16,}'''
]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ Selected runtime/environment overrides:
| `CODEX_TUI_V2=0/1` | Disable/enable TUI v2 |
| `CODEX_TUI_COLOR_PROFILE=truecolor|ansi256|ansi16` | TUI color profile |
| `CODEX_TUI_GLYPHS=ascii|unicode|auto` | TUI glyph style |
| `CODEX_SECRET_STORAGE_MODE` | Token-at-rest backend selection: `keychain`, `plaintext`, or `auto` (`keychain` default; set explicit `keychain` in enterprise deployments) |
| `CODEX_AUTH_FETCH_TIMEOUT_MS=<ms>` | Request timeout override |
| `CODEX_AUTH_STREAM_STALL_TIMEOUT_MS=<ms>` | Stream stall timeout override |

Expand Down
4 changes: 4 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ Before release and after dependency changes:

```bash
npm run audit:ci
npm run ops:health-check
npm run perf:budget-check
npm run sbom:generate
npm run sbom:verify
npm run lint
npm run typecheck
npm test
Expand Down
9 changes: 9 additions & 0 deletions config/performance-budgets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"filterInput_small": 2.0,
"filterInput_large": 10.0,
"cleanupToolDefinitions_medium": 10.0,
"cleanupToolDefinitions_large": 20.0,
"accountHybridSelection_200": 30.0,
"resolveRequestAccountId_1000": 3.0,
"normalizeAccountStorage_240": 20.0
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Loading