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: 15 additions & 10 deletions docs/codex-cloud.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,12 @@ PLAYWRIGHT_OFFLINE_MODE=true
Keep OpenAI disabled unless a later task explicitly authorizes it. Do not add provider keys,
tokens, database URLs, service-role values, E2E credentials, or `ALLOW_PROVIDER_TESTS` to this
environment. The generated agent profile removes the complete provider-variable inventory in
both access profiles. Connected access means the scoped OAuth MCP servers and GitHub connector
are available; it does not mean raw credentials are exposed to the shell.
both access profiles. Connected access configures the repository profile for scoped OAuth MCP
servers and GitHub integration, but it does not expose raw credentials to the shell or guarantee
that every GitHub capability appears as a direct agent tool. For ordinary Cloud task publishing,
use the native Cloud diff/PR controls and verify the resulting GitHub branch and PR link. A
metadata-only `make_pr` response is not publication evidence. If a requested GitHub API is not
available, report that limitation rather than using shell credentials as a workaround.

Codex Cloud secrets and ordinary environment variables have different exposure and lifecycle
properties. This repository has no mechanism that promotes setup-only OpenAI, Supabase, E2E,
Expand All @@ -119,14 +123,15 @@ The GitHub connector is the supported repository/PR path. Follow the official
`BigSimmo/Database` repository, and ensure the installation grants the user write access if
Cloud tasks must publish PRs. Repository discovery proves read access only.

For an explicitly authorised GitHub task, treat the authenticated GitHub connector/MCP
tools as the default remote control plane. Use the connector for repository and PR reads,
issue and PR comments, inline-review-thread replies/resolution, Actions
run/job/log/artifact inspection and retries, and approved branch, file, or PR mutations.
Do not infer that GitHub is unavailable because `gh`, shell GitHub credentials, or
direct shell access are absent. The intended connection is `BigSimmo` with administrator
access to this repository. Use shell `git` or `gh` only for a genuine connector gap and
only when the task permits it.
For an explicitly authorised GitHub task, use Cloud's authenticated GitHub integration
as the remote control plane. For ordinary Cloud work, publish through the native task
diff/PR controls and verify the returned GitHub branch and pull-request link. Do not infer
that GitHub is unavailable merely because `gh`, shell Git credentials, or a particular
direct agent tool are absent. The intended GitHub identity is `BigSimmo`. Use repository
write access for branch and pull-request publication; reserve administrator access for separately
approved operations. Some GitHub APIs, including review-thread or Actions management,
may not be exposed in every Cloud task; use an approved GitHub-connected workflow for those
operations or report the unavailable capability. Do not use shell credentials as a workaround.

GitHub connector permission is separate from credentials inside the agent shell. Do
not add a personal access token to Cloud secrets or environment variables to make
Expand Down
15 changes: 15 additions & 0 deletions scripts/check-codex-cloud-setup.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,21 @@ export function validateCodexCloudSetup() {
[/@openai\/codex/, "Cloud setup must install the Codex CLI."],
[/ensure-codex-cloud-git-remote\.mjs/, "Cloud setup must restore a safe origin remote."],
[/check:codex-cloud -- --runtime/, "Cloud setup must run runtime acceptance."],
[
/BEGIN clinical-kb-codex-cloud shell policy/,
"Cloud setup must write the Codex shell policy inside a managed marker block.",
],
[
/Unmanaged \[shell_environment_policy\] table found/,
"Cloud setup must reject unmanaged shell_environment_policy tables before rewriting config.toml.",
],
[/Incomplete managed shell policy block/, "Cloud setup must reject incomplete managed shell policy marker blocks."],
[
/export RAG_PROVIDER_MODE="\$\{rag_provider_mode\}"/,
"Cloud setup must pin the connected-mode retrieval value at setup time.",
],
[/inherit = "all"/, "Cloud setup must configure Codex shell_environment_policy inheritance."],
Comment thread
cursor[bot] marked this conversation as resolved.
[/CODEX_CLOUD_SETUP_STOP_AFTER_POLICY/, "Cloud setup must expose a policy-only stop for behavior-level tests."],
]) {
requireMatch(errors, setup, pattern, message);
}
Expand Down
99 changes: 97 additions & 2 deletions scripts/setup-codex-cloud.sh
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,26 @@ if [[ "$(npm --version)" != "$expected_npm_version" ]]; then
hash -r
fi

access_profile="${CODEX_CLOUD_ACCESS_PROFILE:-offline}"
case "$access_profile" in
offline|connected) ;;
*) fail "Unsupported CODEX_CLOUD_ACCESS_PROFILE: $access_profile" ;;
esac

# Resolve the retrieval mode at setup time so the generated profile pins the
# value configured in the Codex environment. The agent shell does not inherit
# these variables, so a runtime `${RAG_PROVIDER_MODE:-auto}` fallback would
# override a connected environment configured for offline retrieval.
if [[ "$access_profile" = "connected" ]]; then
rag_provider_mode="${RAG_PROVIDER_MODE:-auto}"
case "$rag_provider_mode" in
auto|openai|offline) ;;
*) fail "Unsupported RAG_PROVIDER_MODE: $rag_provider_mode" ;;
esac
else
rag_provider_mode="offline"
fi

runtime_profile="$HOME/.clinical-kb-codex-cloud.sh"
cat > "$runtime_profile" <<EOF
# Generated by scripts/setup-codex-cloud.sh. Re-running setup replaces this file.
Expand All @@ -69,7 +89,7 @@ fi
export PATH="\$HOME/.local/bin:\$HOME/.deno/bin:\$HOME/.cache/clinical-kb-codex/ocr-venv/bin:\$PATH"
export CODEX_CLOUD_OCR_PYTHON="\$HOME/.cache/clinical-kb-codex/ocr-venv/bin/python"
export CODEX_CLOUD=1
export CODEX_CLOUD_ACCESS_PROFILE="\${CODEX_CLOUD_ACCESS_PROFILE:-offline}"
export CODEX_CLOUD_ACCESS_PROFILE="${access_profile}"
export NEXT_PUBLIC_DEMO_MODE="\${NEXT_PUBLIC_DEMO_MODE:-true}"
export PLAYWRIGHT_OFFLINE_MODE="\${PLAYWRIGHT_OFFLINE_MODE:-true}"
unset npm_config_http_proxy npm_config_https_proxy npm_config_proxy
Expand All @@ -87,7 +107,7 @@ unset GH_TOKEN GITHUB_TOKEN GITLAB_TOKEN GLAB_TOKEN CODEX_TRIGGER_TOKEN
unset HEALTH_DEEP_PROBE_SECRET INDEXING_V3_AGENT_SECRET
unset E2E_AUTH_ENABLED E2E_USER_EMAIL E2E_USER_PASSWORD ALLOW_PROVIDER_TESTS
if [ "\$CODEX_CLOUD_ACCESS_PROFILE" = "connected" ]; then
export RAG_PROVIDER_MODE="\${RAG_PROVIDER_MODE:-auto}"
export RAG_PROVIDER_MODE="${rag_provider_mode}"
else
export CODEX_CLOUD_ACCESS_PROFILE=offline
export RAG_PROVIDER_MODE=offline
Expand All @@ -96,6 +116,81 @@ else
fi
EOF

# Codex spawns commands through a policy in ~/.codex/config.toml. Inheriting the
# whole environment while relying only on the CLI's name-based default excludes
# leaks provider variables that do not look credential-like (e.g. SUPABASE_URL,
# DATABASE_URL) into shells that never source the runtime profile above, so
# exclude the full provider inventory explicitly. Only the managed block is
# rewritten; any other Codex CLI settings (mcp_servers, model, profiles, notify)
# already in the file are preserved across setup/maintenance re-runs.
codex_shell_policy_excludes=(
OPENAI_API_KEY OPENAI_ORG_ID OPENAI_PROJECT_ID OPENAI_BASE_URL
NEXT_PUBLIC_SUPABASE_URL NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY NEXT_PUBLIC_SUPABASE_ANON_KEY
SUPABASE_URL SUPABASE_ANON_KEY SUPABASE_PUBLISHABLE_KEY SUPABASE_SECRET_KEY
SUPABASE_PROJECT_REF SUPABASE_PROJECT_NAME SUPABASE_STAGING_PROJECT_REF SUPABASE_STAGING_PROJECT_NAME
SUPABASE_ACCESS_TOKEN SUPABASE_SERVICE_ROLE_KEY SUPABASE_DB_URL DATABASE_URL POSTGRES_PASSWORD
CROSS_TENANT_SERVICE_ROLE_KEY
RAILWAY_API_TOKEN RAILWAY_TOKEN
GH_TOKEN GITHUB_TOKEN GITLAB_TOKEN GLAB_TOKEN CODEX_TRIGGER_TOKEN
HEALTH_DEEP_PROBE_SECRET INDEXING_V3_AGENT_SECRET
E2E_AUTH_ENABLED E2E_USER_EMAIL E2E_USER_PASSWORD ALLOW_PROVIDER_TESTS
)
codex_exclude_toml=""
for exclude_var in "${codex_shell_policy_excludes[@]}"; do
[[ -n "$codex_exclude_toml" ]] && codex_exclude_toml+=", "
codex_exclude_toml+="\"$exclude_var\""
done

codex_config_dir="$HOME/.codex"
codex_config_file="$codex_config_dir/config.toml"
mkdir -p "$codex_config_dir"
codex_policy_begin="# BEGIN clinical-kb-codex-cloud shell policy (managed by setup-codex-cloud.sh)"
codex_policy_end="# END clinical-kb-codex-cloud shell policy (managed by setup-codex-cloud.sh)"
if [[ -f "$codex_config_file" ]]; then
# An interrupted prior write can leave BEGIN without END. The sed range below
# would then delete from BEGIN to EOF and discard unrelated settings, so fail
# before rewriting rather than silently truncating preserved config.
if grep -Fq "$codex_policy_begin" "$codex_config_file" && ! grep -Fq "$codex_policy_end" "$codex_config_file"; then
fail "Incomplete managed shell policy block in $codex_config_file; remove the incomplete BEGIN marker before re-running setup."
fi
codex_config_preserved="$(sed "/^${codex_policy_begin}\$/,/^${codex_policy_end}\$/d" "$codex_config_file")"
# After stripping the managed block, reject every supported TOML declaration
# of shell_environment_policy before appending ours. This covers bare or
# quoted table headers, dotted keys, and inline tables, while full-line
# comments are ignored.
if printf '%s\n' "$codex_config_preserved" | sed '/^[[:space:]]*#/d' | grep -Eq \
'^[[:space:]]*\[[^]]*shell_environment_policy[^]]*\]|^[[:space:]]*[^[:space:]]*shell_environment_policy[^[:space:]]*[[:space:]]*\.|^[[:space:]]*[^[:space:]]*shell_environment_policy[^[:space:]]*[[:space:]]*=[[:space:]]*\{'; then
fail "Unmanaged [shell_environment_policy] table found in $codex_config_file; remove it before re-running setup."
fi
else
codex_config_preserved=""
fi

# Write beside the destination then rename it atomically. If setup is
# interrupted or output fails, the existing Codex configuration remains intact.
codex_config_candidate="$(mktemp "$codex_config_dir/.config.toml.XXXXXX")"
trap 'rm -f "$codex_config_candidate"' EXIT
{
if [[ -n "$codex_config_preserved" ]]; then
printf '%s\n' "$codex_config_preserved"
fi
Comment thread
cursor[bot] marked this conversation as resolved.
printf '%s\n' "$codex_policy_begin"
printf '[shell_environment_policy]\n'
Comment thread
cursor[bot] marked this conversation as resolved.
printf 'inherit = "all"\n'
printf 'ignore_default_excludes = false\n'
printf 'exclude = [%s]\n' "$codex_exclude_toml"
printf '%s\n' "$codex_policy_end"
} > "$codex_config_candidate"
mv -f "$codex_config_candidate" "$codex_config_file"
trap - EXIT

# Test harness only: write the runtime profile + shell policy, then stop before
# toolchain installs so unit tests can exercise config merge without npm/Playwright.
if [[ "${CODEX_CLOUD_SETUP_STOP_AFTER_POLICY:-0}" = "1" ]]; then
log "Stopping after shell-policy write (test harness)."
exit 0
fi

Comment thread
coderabbitai[bot] marked this conversation as resolved.
profile_source='[ -f "$HOME/.clinical-kb-codex-cloud.sh" ] && . "$HOME/.clinical-kb-codex-cloud.sh"'
for shell_profile in "$HOME/.bashrc" "$HOME/.profile" "$HOME/.bash_profile"; do
touch "$shell_profile"
Expand Down
Loading
Loading