Skip to content

Bound inactive Codex server generation scans without blocking history #104

Description

@pchalasani

Context

PR #101 introduced versioned Codex app-server generations. Its review identified
that stopped generation directories accumulated until the 256-directory scan cap
blocked both startup and forced cleanup. PR #103 fixed that failure by excluding
inactive directories that retain neither state.json nor a generation socket from
the live and cleanup candidate limits.

The automated review on PR #103 identified the other side of this tradeoff:
inactive 24-hex generation directories now bypass both
MAX_SERVER_DIRECTORY_ENTRIES and MAX_SERVER_GENERATION_DIRECTORIES.
all_server_paths() still validates and probes every such directory, so a corrupted
or deliberately populated user-owned CODEX_HOME can force unbounded filesystem
work on every startup and codex-server stop --force.

Impact

This is a local resource-exhaustion or denial-of-service risk. It requires many
entries in the user-owned Codex runtime directory; it does not provide privilege
escalation, corrupt workflow data, or disconnect sessions by itself. Ordinary
history is unlikely to cause noticeable delay, but the implementation no longer
upholds its bounded-scan invariant.

Required Properties

  • Bound CPU, memory, and filesystem operations for hostile or corrupted stores.
  • Do not let ordinary inactive history permanently block startup or forced cleanup.
  • Retain the 64-live-generation limit.
  • Preserve fail-closed handling for live, unsafe, symlinked, foreign-owned, or
    unverifiable generation entries.
  • Do not delete or rename a generation without safely proving that operation is
    valid.
  • Keep lifecycle commands recoverable after interruption.

Simply counting inactive directories toward the old cap is not a fix because it
restores the PR #101 failure. Possible designs include a separate bounded history
namespace, a durable generation index, or incremental cleanup with durable
progress. The design should stay smaller than the abandoned generalized retention
subsystem explored during the PR #103 follow-up.

Acceptance Tests

  • More than 256 legitimate inactive histories do not block normal startup or forced
    cleanup.
  • Very large sets of valid inactive names cannot cause unbounded traversal.
  • Mixed inactive and live generations preserve every live generation and enforce
    the live cap.
  • Unsafe names, symlinks, ownership violations, and replacement races remain
    fail-closed.
  • Interrupted maintenance can resume without leaving permanent capacity blockers.

Related: #101, #103.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions