#1156

refactor(security): remove counted compatibility paths scheduled for 0.19.0

Openiamgpwants to merge intofrom

Completes the part of the 0.19.0 removal schedule that covers compatibility paths with phlo.legacy.*.uses counters (ADR 0053 decision 4 and exit criteria). Each path is removed with its warning, counter, tests of the deprecated behaviour and documentation.

Removed paths and replacements

RemovedCounter removedReplacement
PHLO_REGULATED_MODE environment fallback; phlo.yaml regulated_mode key; is_regulated_mode_enabled, PHLO_REGULATED_MODE_ENV, get_regulated_mode_config (config and infrastructure), create_regulated_mode_bridge, run_regulated_mode_validation, require_regulated_mode_validationphlo.legacy.regulated_mode_env.usesPHLO_REGULATED or regulated: true; is_regulated, PHLO_REGULATED_ENV, get_regulated_config, create_regulated_bridge, run_regulated_validation, require_regulated_validation
Legacy Dagster .phlo/.env and .phlo/.env.local attachment per generated Phlo-dev servicephlo.legacy.dagster_env_file.usesphlo services migrate to .phlo/overrides/.env and .phlo/secrets/.env
Legacy MCP JSONL debug tracing: --trace-file, PHLO_MCP_TRACE_FILE, McpTraceSettings, McpConfig.trace_file, configure_tracing, load_spans, render_trace_treephlo.legacy.mcp_jsonl_span.usesOBSERVE_DRAINS or OBSERVE_HTTP_ENDPOINT; canonical MCP operation scopes and trace queries are unchanged

Behaviour after removal

  • A phlo.yaml regulated_mode key fails validation with a message naming regulated, instead of being ignored. A stale key therefore cannot silently turn regulated mode off. Root-level phlo.yaml validation errors now include their message (previously the field list was empty for them).
  • phlo services init, add and remove stop with a CLI error naming phlo services migrate while .phlo/.env or .phlo/.env.local exists. Migrated and new projects get env_file: [overrides/.env, secrets/.env] as before. phlo services migrate is unchanged.
  • PHLO_REGULATED_MODE no longer configures anything, but it still fails closed when stale: is_regulated() (and so requires_http_authorization()) raises naming PHLO_REGULATED when the removed variable is set and neither PHLO_REGULATED nor explicit configuration decides the result. The Compose override-layer guard still treats a true value as protected.
  • phlo services migrate no longer requires .phlo/.env, so a project holding only .phlo/.env.local can migrate. The phlo.yaml template, generated Compose header, env header and production-credential message now point secrets at .phlo/secrets/.env.

Verification

  • make check passes; make test-core-regression passes.
  • phlo-mcp package tests pass; the tool-tracing test now asserts nesting and outcomes from canonical observe events instead of the JSONL file.
  • Manual: legacy-layout project → phlo services init --force fails with the migration message → phlo services migrate → regeneration attaches only the shared files. docker compose config --quiet passes on a freshly generated stack.
  • registry/support/v1.json does not reference these paths; unchanged.

    

Activity

313
coldtea-pr-lens[bot]3h ago
  • Redraw · drawn at 91a15b6, the branch has moved on

Architecture

Inside the changed components — 2 views

Component view — Security & RBAC

Regulated mode configuration and validation components with removed aliases

Component view — MCP Server Tracing

MCP server instrumentation updated to remove custom JSONL trace drain

Data flow


Review

✨ Nothing flagged · reviewed 91a15b6


TIP

Click the link under each diagram to open it on a canvas you can zoom, pan and step through

🪧 More tips
  • Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists
  • The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change
  • Open a diagram on the canvas, then press W or click play to walk through the change one step at a time
  • The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time
  • Set github.comment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture… row. Drawing still runs as before
  • Set github.draw: on-demand in .github/pr-lens.yml and PR Lens stops drawing pull requests on its own. Comment @pr-lens draw on a pull request when you want that one drawn
  • Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works
  • After a push, tick Redraw to draw the latest commit
  • Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion
  • Set github.description: false in .github/pr-lens.yml to stop PR Lens adding buttons to your PR descriptions

Thanks for using PR Lens! It's free for OSS. If it helped, a star helps other teams find it. 

phlo-agent[bot]3h ago

Reviewed 91a15b6 against the full diff, ADR 0065, the migrate/upgrade call paths, and the settings/env inventories. Two issues, both in the "removed successfully" story rather than the removals themselves.

1. PHLO_REGULATED_MODE now turns regulated mode off silently

src/phlo/security/mode.py:38-55 removes the fallback, and tests/security/test_mode.py adds test_removed_regulated_mode_env_is_ignored to lock in the silence. A deployment whose only regulated signal was the deprecated variable now reports unregulated with no warning or error: requires_http_authorization() no longer forces authentication for it, phlo services init --observatory-dev no longer refuses (src/phlo/cli/commands/services/init.py, _configure_observatory_dev), and the Compose override guard keyed off the same predicate stops refusing layers.

That is the same outcome the description rejects for the regulated_mode key — "a stale key cannot silently turn regulated mode off" — and the new reject_removed_regulated_mode validator in src/phlo/config_schema.py enforces it there. Leaving the environment spelling fail-open makes the security posture depend on which spelling a deployment happened to keep.

Suggestion: keep a presence check for the removed name and raise (or warn once, as the deprecation did) naming PHLO_REGULATED when it is set, then assert that failure instead of the current silent-ignore test.

2. A lone .phlo/.env.local can neither init nor migrate

The new guard in src/phlo/plugins/compose/generator.py:413-419 raises whenever either legacy file exists, and every regeneration command routes that to "run phlo services migrate". But phlo services migrate starts from ensure_compose_project() (src/phlo/cli/commands/services/utils.py:99-113), which requires env_defaults_path(...), i.e. .phlo/.env for a legacy layout (src/phlo/config/layout.py:26-28). A project holding only .phlo/.env.local therefore gets "run phlo services init" from migrate and "run phlo services migrate" from init/add/remove/upgrade, and only manual file renaming recovers. Before this change init repaired that state by regenerating .phlo/.env and attaching .env.local.

The state is reachable through the repository's own guidance, which this PR leaves in place: PHLO_CONFIG_TEMPLATE in utils.py:80 tells new projects "Secrets belong in .phlo/.env.local (not committed)" (written into their phlo.yaml), and the generated Compose header in generator.py:152 still says "Modify ... .phlo/.env.local for secrets". New projects are shared-layout, so those paths are no longer read — and creating one now blocks every command that regenerates Compose.

Suggestion: point the template and header at .phlo/overrides/.env / .phlo/secrets/.env, and let migrate handle a missing defaults file (or have the new error spell out the manual move to .phlo/secrets/.env) so the documented recovery path actually exists.

Checked without findings

The phlo-mcp removal is self-contained in the reviewed modules (server.py, cli.py, cli_plugin.py, _tools_traces.py); the generated settings references (333 fields / 52 models), tests/tooling/phlo_env_reads_inventory.json, and docs/reference/python-api.md are consistent; registry/support/v1.json mentions none of the removed names. CI checks at this SHA were still running when I reviewed (only PR Lens had finished), so the description's make check claim is unverified here; this is static inspection only, no code executed.