Skip to content

feat(selfhost): wire Codex reviews and secure observability#1678

Open
JSONbored wants to merge 68 commits into
mainfrom
codex/selfhost-codex-reviewer
Open

feat(selfhost): wire Codex reviews and secure observability#1678
JSONbored wants to merge 68 commits into
mainfrom
codex/selfhost-codex-reviewer

Conversation

@JSONbored

@JSONbored JSONbored commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add Codex CLI runtime support for self-hosted reviews while preserving Claude Code and Ollama paths.
  • Make provider configuration explicit with CODEX_AI_*, CLAUDE_AI_*, OLLAMA_AI_*, OPENAI_COMPATIBLE_AI_*, OPENAI_AI_*, and ANTHROPIC_AI_* settings instead of shared ambiguous AI knobs.
  • Reject deprecated shared AI env knobs at startup with a clear provider-specific migration error so stale AI_MODEL, AI_EFFORT, AI_BASE_URL, AI_API_KEY, or AI_TIMEOUT_MS values cannot silently steer the wrong backend.
  • Prefer repo-scoped AGENTS.md for Codex review context while preserving CLAUDE.md fallback and skills loading.
  • Restore the maintainer Reviews & PRs Grafana dashboard through a redacted reporting SQLite export instead of direct Grafana access to the live app database.
  • Add Codex usage observability, Sentry-facing provider failure context, self-host docs, and default blank optional-profile env values so inactive profiles do not warn.
  • Automate self-host Sentry release/source-map handling so release images bake a matching gittensory-selfhost@<version> release id and the release workflow uploads the exact built bundle maps.
  • Fix maintainer-lane preflight handling so owner/member/collaborator self-host work is not held solely because repo registration is unavailable, while outside contributors still get the conservative hold.

Closes #1469.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format, for example fix(api): restore profile access checks.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked an issue, or this is small enough that the summary explains why an issue is not needed.

Validation

  • git diff --check
  • npm run actionlint
  • npm run typecheck
  • npm run test:coverage locally; codecov/patch requires >=97% coverage of the lines AND branches you changed (aim for 98%+ on your diff so CI variance does not fail near the threshold). Global coverage is a non-blocking trend with a loose 90% backstop, not the gate.
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint
  • npm run ui:typecheck
  • npm run ui:build
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

Additional validation:

  • npm run test:ci
  • npm run typecheck
  • npx vitest run test/unit/selfhost-grafana-reporting.test.ts test/unit/selfhost-ai.test.ts test/unit/ai-review-advisory.test.ts
  • npx vitest run test/unit/signals-coverage.test.ts test/unit/selfhost-ai.test.ts
  • GRAFANA_ADMIN_PASSWORD=placeholder docker compose --profile observability config
  • Reporting exporter smoke: missing source creates a valid empty redacted reporting database, real SQLite source exports dashboard-safe review and AI usage rows, quoted paths are handled safely, private review columns are absent, and AI metadata is reduced to repo/PR fields.
  • Reporting exporter schema test: current source DBs export estimated_neurons; older source DBs without that column still materialize a valid dashboard-safe estimated_neurons = 0 column.
  • node scripts/build-selfhost.mjs --all --sourcemap
  • Release workflow source-map invariant: confirmed dist/server.mjs, dist/server.mjs.map, sourceMappingURL=server.mjs.map, non-empty original sources, and sourceRoot=/app/dist.
  • Docker build smoke: default self-host image target and runtime-prebuilt release target both build successfully.
  • Visual-review release image smoke: runtime-prebuilt with INSTALL_VISUAL_REVIEW=true installs puppeteer-core successfully.
  • Release-target image check: confirmed baked GITTENSORY_VERSION, NODE_OPTIONS=--enable-source-maps, dist/server.mjs, dist/server.mjs.map, and source map sourceRoot=/app/dist.
  • Grafana dashboard JSON parse check for resource hub, infra, Codex usage, and maintainer dashboards.
  • Self-host smoke: rebuilt the app service, confirmed /ready, confirmed Codex review settings and auth mount behavior, confirmed Codex reviews completed, and confirmed Codex token/request metrics increased.

If any required check was skipped, explain why:

  • A fresh live-stack redeploy was not repeated for the latest head; the current head is covered by local config, exporter, build, source-map, and image smoke checks.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests.
  • API/OpenAPI/MCP behavior is updated and tested where needed.
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks.
  • Visible UI changes include a UI Evidence section below with JPG/JPEG or PNG screenshots arranged as organized, captioned, clickable thumbnails. SVG screenshots are not used as review evidence. Review-only screenshots or recordings are not committed to the repository.
  • Public docs/changelogs are updated where needed; changelogs are only edited for release-prep PRs.

UI Evidence

State / title JPG/PNG evidence
Operator Grafana dashboard Not an app UI surface; verified through Grafana provisioning and datasource checks. The dashboard uses the redacted reporting database instead of direct live database access.

Notes

@codecov

codecov Bot commented Jun 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.95058% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 95.68%. Comparing base (29da3b1) to head (9bd1a2b).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/queue/processors.ts 78.78% 2 Missing and 12 partials ⚠️
src/services/ai-review.ts 93.05% 0 Missing and 5 partials ⚠️
src/github/app.ts 94.28% 0 Missing and 4 partials ⚠️
src/signals/engine.ts 94.02% 0 Missing and 4 partials ⚠️
src/github/backfill.ts 93.75% 0 Missing and 1 partial ⚠️
src/selfhost/ai.ts 99.36% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1678      +/-   ##
==========================================
+ Coverage   95.59%   95.68%   +0.09%     
==========================================
  Files         204      211       +7     
  Lines       22316    22985     +669     
  Branches     8067     8310     +243     
==========================================
+ Hits        21332    21994     +662     
+ Misses        408      402       -6     
- Partials      576      589      +13     
Files with missing lines Coverage Δ
src/config/gittensory-repo-focus-manifest.ts 100.00% <ø> (ø)
src/db/repositories.ts 96.16% <ø> (ø)
src/db/schema.ts 68.32% <ø> (ø)
src/github/comments.ts 100.00% <100.00%> (+3.22%) ⬆️
src/github/self-authored.ts 100.00% <100.00%> (ø)
src/github/webhook.ts 100.00% <100.00%> (ø)
src/index.ts 94.64% <100.00%> (+2.80%) ⬆️
src/queue/dlq.ts 100.00% <100.00%> (ø)
src/queue/retryable.ts 100.00% <100.00%> (ø)
src/review/ai-notes.ts 100.00% <100.00%> (ø)
... and 27 more
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored JSONbored marked this pull request as ready for review June 28, 2026 12:47
@JSONbored JSONbored self-assigned this Jun 28, 2026
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Jun 28, 2026

@superagent-security superagent-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superagent found 1 security concern(s).

Comment thread docker-compose.yml Outdated
@superagent-security superagent-security Bot added the pr:flagged PR flagged for review by security analysis. label Jun 28, 2026
@JSONbored JSONbored force-pushed the codex/selfhost-codex-reviewer branch from 74f4dcc to d89d349 Compare June 28, 2026 13:21
@superagent-security superagent-security Bot removed the pr:flagged PR flagged for review by security analysis. label Jun 28, 2026
@JSONbored JSONbored force-pushed the codex/selfhost-codex-reviewer branch from d89d349 to f4aa25e Compare June 28, 2026 13:25
@JSONbored JSONbored changed the title feat(selfhost): enable Codex review runtime support feat(selfhost): wire Codex reviews and secure observability Jun 28, 2026
@gittensory-orb

gittensory-orb Bot commented Jun 28, 2026

Copy link
Copy Markdown

Caution

🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥

🛑 Gittensory review result - fixes required

Review updated: 2026-06-29 16:22:56 UTC

116 files · 1 AI reviewer · 1 blocker · readiness 75/100 · CI failing · blocked

🛑 Suggested Action - Manual Review

  • The AI review flagged a possible must-fix defect below the automatic close-confidence floor, so the gate is held for a human reviewer instead of passed automatically.

Review summary
This wires self-host review execution through provider-specific AI config, Codex/Claude CLI adapters, Redis-backed queues, and redacted reporting dashboards while retiring hosted review execution. The queue and AI changes mostly preserve fail-closed behavior and add useful observability, but the readiness enforcement change breaks the settings contract by leaving a blocking UI/config option that the engine now ignores.

Blockers

  • apps/gittensory-ui/src/components/site/app-panels/maintainer-settings.tsx:158 still exposes `qualityGateMode` with `block`, but src/rules/advisory.ts:911 now converts low readiness into a warning for every non-off mode, so an operator selecting block silently gets advisory behavior instead of an enforced check.
Nits — 7 non-blocking
  • Dockerfile:49 still installs global CLI packages without a lockfile or artifact verification; `--foreground-scripts` improves visibility, but release images still depend on mutable transitive npm resolution.
  • src/selfhost/ai-config.ts:46 treats `codex` as configured even when `createCodexAi` will reject until the explicit unsafe opt-in is set, so boot diagnostics and reviewer labels can advertise a reviewer that will only fail closed.
  • src/selfhost/pg-queue.ts:332 and src/selfhost/sqlite-queue.ts:254 intentionally do not increment attempts for rate-limit retries; add a comment or focused test so this non-consuming retry behavior is not mistaken for a dropped retry counter.
  • Either restore readiness blocking in src/rules/advisory.ts for `qualityGateMode: block`, or remove/disable the block option for `qualityGateMode` in apps/gittensory-ui/src/components/site/app-panels/maintainer-settings.tsx and the config/docs surfaces that still advertise it.
  • For the bundled CLIs in Dockerfile:49, prefer a reproducible install path with committed package metadata, verified binary downloads, or an explicit integrity check before publishing official images.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.
  • AI reviewers agree on a likely critical defect: apps/gittensory-ui/src/components/site/app-panels/maintainer-settings.tsx:158 still exposes `qualityGateMode` with `block`, but src/rules/advisory.ts:911 now converts low readiness into a warning for every non-off mode, so an operator selecting block silently gets advisory behavior instead of an enforced check. — Resolve the flagged defect, or override if the AI reviewers are mistaken, then re-run the gate.

Why this is blocked

  • apps/gittensory-ui/src/components/site/app-panels/maintainer-settings.tsx:158 still exposes `qualityGateMode` with `block`, but src/rules/advisory.ts:911 now converts low readiness into a warning for every non-off mode, so an operator selecting block silently gets advisory behavior instead of an enforced check.

CI checks failing

  • codecov/patch — 96.95% of diff hit (target 97.00%)
Signal Result Evidence
Code review ❌ 1 blocker 1 reviewer
Linked issue ✅ Linked #1469
Related work ⚠️ 2 scoped overlaps Top overlaps are listed below; lower-confidence bulk is hidden.
Review load ❌ 8/20 Readiness component derived from cached public PR metadata and labels; size label size:L.
Validation evidence ✅ 25/25 PR body includes validation/test evidence.
Open PR queue ❌ 3/10 25 open PR(s), 12 likely reviewable, 13 unlinked.
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 74 PR(s), 280 issue(s).
Gate result ⚠️ Not blocking Advisory; not blocking this PR.
Review context
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Review top overlaps.
  • Add scope summary.
  • Expect slower review.
  • No action.
  • Check active issues and PRs before submitting.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Review load = cached public PR metadata such as size labels, changed paths, and preflight status.
  • Open PR queue = repo-wide review pressure; it is not a PR quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@gittensory-orb gittensory-orb Bot added gittensor Gittensor contributor context gittensor:feature Gittensor-scored feature linked to a feature issue - worth 1.25x multiplier. labels Jun 28, 2026

@superagent-security superagent-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superagent found 1 security concern(s).

Comment thread .github/workflows/release-selfhost.yml Outdated
@superagent-security superagent-security Bot added pr:flagged PR flagged for review by security analysis. and removed pr:flagged PR flagged for review by security analysis. labels Jun 28, 2026
@JSONbored

Copy link
Copy Markdown
Owner Author

@gittensory gate-override Maintainer-lane self-host setup PR: all CI, security, coverage, and self-host smoke checks are green. The remaining blocker is the deployed gate readiness/preflight hold for owner-authored work when repo registration is unavailable, and this PR includes the upstream fix for that false-positive.

@superagent-security superagent-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\nSuperagent found 2 security concern(s).

Comment thread docker-compose.yml Outdated
Comment thread scripts/export-grafana-reporting-db.sh Outdated
@superagent-security superagent-security Bot added pr:flagged PR flagged for review by security analysis. and removed pr:flagged PR flagged for review by security analysis. labels Jun 28, 2026
@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Jun 28, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 28, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
gittensory-ui 9d7d044 Commit Preview URL

Branch Preview URL
Jun 29 2026, 11:31 AM

@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XXL This PR changes 1000+ lines, ignoring generated files. labels Jun 29, 2026

@superagent-security superagent-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superagent found 2 security concern(s).

Comment thread Dockerfile Outdated
&& chown -h node:node /home/node/.codex \
&& chown -R node:node /home/node/.npm-global /home/node/.npm
USER node
RUN if [ "$INSTALL_AI_CLIS" = "true" ]; then npm install -g @anthropic-ai/[email protected] @openai/[email protected]; fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Docker image build executes npm postinstall scripts from global CLI packages

The Dockerfile installs @anthropic-ai/claude-code and @openai/codex globally via npm install -g without --ignore-scripts, allowing postinstall lifecycle scripts from these packages and their transitive dependencies to execute during the Docker image build.

Add --foreground-scripts to make postinstall execution visible in build logs, and audit the CLI packages and their transitive dependencies with npm audit before image publication. Consider using reproducible installs with a lock file for global dependencies.

AI prompt
Check if this security scanner issue is valid. If so, understand the root cause and fix it. If appropriate, update or add tests. Keep the change focused and preserve intended behavior.

<file name="Dockerfile">
<violation number="1" location="Dockerfile:49">
<priority>P2</priority>
<title>Docker image build executes npm postinstall scripts from global CLI packages</title>
<evidence>The runtime-base stage in the Dockerfile runs npm install -g @anthropic-ai/[email protected] @openai/[email protected] as the unprivileged node user without the --ignore-scripts flag. This executes any postinstall scripts defined in these packages and their transitive dependencies during the Docker build. Because npm install -g does not use a lock file for transitive dependencies, their versions can shift between builds based on upstream semver ranges, increasing supply-chain risk.</evidence>
<recommendation>Add --foreground-scripts to the npm install -g command so postinstall execution is visible in build logs. Run npm audit against the installed CLI packages before image publication. Consider pinning transitive dependency versions by generating and verifying a lock file for the global install, or install the native binaries via direct verified downloads instead of npm to eliminate script execution entirely.</recommendation>
</violation>
</file>

Comment thread scripts/deploy-selfhost-prebuilt.sh Outdated
-v "$PWD:/work" \
-w /work \
"$NODE_IMAGE" \
sh -lc 'apt-get update >/dev/null && apt-get install -y --no-install-recommends ca-certificates git >/dev/null && git config --global --add safe.directory /work && (npx -y @sentry/cli@latest releases new "$SENTRY_RELEASE" >/tmp/gittensory-sentry-release-new.log 2>&1 || true) && npx -y @sentry/cli@latest releases set-commits "$SENTRY_RELEASE" --auto && npx -y @sentry/cli@latest sourcemaps inject dist && node scripts/validate-selfhost-sourcemap.mjs && npx -y @sentry/cli@latest sourcemaps upload --release="$SENTRY_RELEASE" dist && npx -y @sentry/cli@latest releases finalize "$SENTRY_RELEASE" && chown -R "$HOST_UID:$HOST_GID" dist node_modules package-lock.json'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Deploy script fetches and runs unpinned Sentry CLI via npx

The self-host deploy script invokes npx -y @sentry/cli@latest multiple times to manage Sentry releases and upload source maps. Using @latest means any compromised Sentry CLI release could execute arbitrary code during deployment with access to SENTRY_AUTH_TOKEN and the mounted project directory.

Pin the Sentry CLI to a specific version (e.g., @sentry/[email protected]) consistent with the release workflow, and verify the installed package integrity before execution. Replace npx -y @sentry/cli@latest with the pinned version throughout the script.

AI prompt
Check if this security scanner issue is valid. If so, understand the root cause and fix it. If appropriate, update or add tests. Keep the change focused and preserve intended behavior.

<file name="scripts/deploy-selfhost-prebuilt.sh">
<violation number="1" location="scripts/deploy-selfhost-prebuilt.sh:158">
<priority>P2</priority>
<title>Deploy script fetches and runs unpinned Sentry CLI via npx</title>
<evidence>The run_sentry_upload function executes npx -y @sentry/cli@latest for releases new, releases set-commits, sourcemaps inject, sourcemaps upload, and releases finalize. The @latest tag fetches the most recent published version without integrity verification. If the Sentry npm package or its dependencies are compromised, arbitrary code executes inside the throwaway Docker container with access to the SENTRY_AUTH_TOKEN environment variable and the $PWD:/work volume mount, allowing modifications to persist on the host filesystem after the container exits.</evidence>
<recommendation>Pin the Sentry CLI version explicitly (e.g., npx -y @sentry/[email protected]) to match the version used in the official release pipeline. Consider installing the CLI via npm ci --ignore-scripts with a local package.json and lock file, or use the official Sentry CLI binary downloaded directly from GitHub releases with checksum verification.</recommendation>
</violation>
</file>

@superagent-security superagent-security Bot added the pr:flagged PR flagged for review by security analysis. label Jun 29, 2026
@superagent-security superagent-security Bot removed the pr:flagged PR flagged for review by security analysis. label Jun 29, 2026
Merge main into the self-host review branch, preserve the pinned Sentry release path, and drop Cloudflare review bindings from gittensory-api now that review execution is self-host-only.

Validation:

- npm run test:ci

- npm audit --audit-level=moderate
Hold missing AI public output as a visible manual-review signal with Sentry context instead of publishing a deterministic-only surface.

Honor QDRANT_DIM during collection initialization and add regression coverage for renamed checks, guardrail manual holds, self-host routing, provider edge cases, and review-comment signals.
Document that direct review-app webhooks and Cloudflare review jobs are retired while central Orb ingress remains live for self-host relay.

Add an Orb webhook invariant without SELFHOST_TRANSIENT_CACHE and update the stale review-job log name.
@superagent-security superagent-security Bot added the pr:flagged PR flagged for review by security analysis. label Jun 29, 2026
Publish public-safe unstructured AI review text as a non-cacheable manual-review fallback instead of dropping it into deterministic-only output.

Add provider diagnostics to Sentry context and cover the fallback path in AI review and queue tests.
@superagent-security superagent-security Bot removed the pr:flagged PR flagged for review by security analysis. label Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue - worth 1.25x multiplier. gittensor Gittensor contributor context size:L This PR changes 100-499 lines, ignoring generated files.

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

build(selfhost): Sentry source maps, env docs, and Grafana resource-hub link

1 participant