Skip to content

Prepare Legis 1.1.1 hardening release#16

Merged
tachyon-beep merged 14 commits into
mainfrom
codex/legis-1.1.1-release-hardening
Jun 22, 2026
Merged

Prepare Legis 1.1.1 hardening release#16
tachyon-beep merged 14 commits into
mainfrom
codex/legis-1.1.1-release-hardening

Conversation

@tachyon-beep

Copy link
Copy Markdown
Collaborator

Summary

  • prepare v1.1.1 release notes/version/docs
  • harden posture install/rekey/session custody and audit invariants
  • wire env-configured coached API/MCP paths without breaking chill behavior
  • expand release workflow gates and MCP/posture regression coverage

Review

  • solution architecture, systems, Python, and quality reviews completed
  • final pass found no critical or important blockers

Local verification

  • .venv/bin/python -m pytest -q: 1194 passed, 5 skipped
  • .venv/bin/ruff check src tests scripts: passed
  • .venv/bin/mypy: passed
  • uv lock --check: passed
  • .venv/bin/python -m pytest --cov=legis --cov-report=term-missing --cov-report=json --cov-fail-under=88: 92.32% coverage
  • .venv/bin/python -m pytest tests/conformance/test_sei_oracle.py -q: 8 passed
  • .venv/bin/legis policy-boundary-check --root src --repo-root .: PASS
  • .venv/bin/python scripts/check_coverage_floors.py: passed
  • uv build && uvx twine check dist/*: passed
  • npm run build in site: passed

@tachyon-beep tachyon-beep merged commit 8ee58e9 into main Jun 22, 2026
2 checks passed
@tachyon-beep tachyon-beep deleted the codex/legis-1.1.1-release-hardening branch June 22, 2026 21:50

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17a370c8a6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/legis/cli.py
return 1

ledger = PostureLedger(posture_db_url(), initialize=False)
epoch_fp = ledger.current_epoch_fingerprint()

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 Badge Refuse cleanly when the posture DB directory is absent

When legis operator enable --insecure-key-in-env is run before any install has created .weft/legis/, this new current_epoch_fingerprint() read opens an initialize=False SQLite store without creating the parent directory or checking whether the DB path exists. SQLite will raise unable to open database file before the intended epoch_fp is None refusal branch runs, so a fresh repo gets a traceback instead of the friendly fail-closed message and exit code. Check the posture DB path (as read_floor() does) or catch the store read failure before this call.

Useful? React with 👍 / 👎.

run: uv sync --dev

- name: Verify lockfile
run: uv lock --check

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 Badge Check the lock before mutating sync

In this workflow, the lock check runs after uv sync --dev. I checked uv sync --help: --locked is the option that asserts uv.lock remains unchanged, while uv lock --check only checks the current lockfile state. If pyproject.toml and uv.lock drift on a release, the preceding sync can refresh uv.lock in the runner and this check then passes, letting publish proceed from an unreviewed lock; run the check before syncing or use uv sync --locked --dev here.

Useful? React with 👍 / 👎.

Comment thread src/legis/cli.py
backend=backend,
)
except Exception as exc: # noqa: BLE001 — custody gap is a fail-closed refusal
except (OperatorKeyCustodyError, RuntimeError, ValueError) as exc:

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 Badge Preserve fail-closed refusal for custody write errors

When rekeying to age-file and the custody path cannot be written (for example .weft/legis is unwritable, the disk is full, or os.replace fails), _default_key_sink can raise OSError from mkdir, mkstemp, or the replace. This handler used to catch all ledger.rekey(...) failures, but now those OS custody failures escape as a traceback instead of the intended posture rekey: refused response with no KEY_RESET written. Include OSError or restore a broader fail-closed catch around the custody handoff.

Useful? React with 👍 / 👎.

Comment thread src/legis/mcp.py
from legis.config import governance_db_url
from legis.enforcement.judge_factory import configured_judge_from_env

judge = configured_judge_from_env("MCP")

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 Badge Handle incomplete judge env as not enabled

For a coached policy when LEGIS_JUDGE_PROVIDER=openrouter is set but the required credentials or token settings are missing/invalid, configured_judge_from_env() raises LLMTransportError here. That bypasses the judge is None disabled path, so policy_explain, policy_list, or override_submit become an internal MCP error instead of the documented actionable “coached not enabled; set provider credentials” response. Catch the configuration error and map it to no coached engine (or NotEnabledError) so partial judge configuration fails closed as an enablement problem.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant