Skip to content

feat(chassis): SDK-native chassis behind L9_CHASSIS + W4-04 audit pool wiring - #150

Open
cryptoxdog wants to merge 2 commits into
mainfrom
feat/sdk-chassis-audit-pool
Open

feat(chassis): SDK-native chassis behind L9_CHASSIS + W4-04 audit pool wiring#150
cryptoxdog wants to merge 2 commits into
mainfrom
feat/sdk-chassis-audit-pool

Conversation

@cryptoxdog

Copy link
Copy Markdown
Collaborator

Why one PR

These two bodies of work share engine/handlers.py and engine/boot.py. The SDK chassis wraps the same GraphLifecycle that W4-04 modifies, and both depend on the new ACTION_HANDLERS registry. Splitting them would mean shipping a broken intermediate state or resolving the same conflict twice.

1. SDK-native chassis — dormant by default

L9_CHASSIS=legacy (the default) preserves today's behavior exactly. L9_CHASSIS=sdk selects the new path.

File Role
chassis/entrypoint.py Single uvicorn target dispatching on L9_CHASSIS
chassis/node_app.py Builds the app via constellation-node-sdk create_node_app
chassis/handler_registration.py Registers ACTION_HANDLERS with the SDK registry + packet audit wrapper

SdkLifecycleAdapter bridges engine.boot.GraphLifecycle (which subclasses the legacy LifecycleHook) onto the SDK's unrelated LifecycleHook ABC. Keeping the adapter in chassis/ means engine/boot.py stays free of SDK imports while both chassis run in parallel.

Every launch site now points at chassis.entrypoint:create_app — Makefile, Dockerfile.prod, scripts/entrypoint.sh, docker-compose.yml — so switching chassis is a config change, not a command change.

Single action registry

engine/handlers.py now exports ACTION_HANDLERS. chassis/actions.py consumes it instead of maintaining its own dict, so the legacy and SDK chassis cannot expose different action sets. tests/contracts/test_chassis_parity.py fails if a future edit reintroduces a hand-maintained list in either one.

2. W4-04 Postgres audit pool

The ComplianceEngine consumer side is already on main; only the wiring was missing.

GraphLifecycle.startup() creates an asyncpg pool when POSTGRES_DSN is set and passes it through init_dependencies() to EngineState.db_pool. shutdown() closes it.

This is a soft dependency: an unset or unreachable DSN leaves db_pool as None and logs a warning rather than blocking startup — the same graceful-degrade pattern as the existing Neo4j connection. EngineState.health_check() reports db_pool_present.

docker-compose.yml gains a postgres:16-alpine service seeded from engine/packet/packet_store.sql.

3. Chassis consolidation

Deletes chassis/app.py (371 lines) and chassis/auth/app.py (208 lines), which duplicated chassis/chassis_app.py. All imports and launch sites repointed. This clears the chassis/auth/app.py item in memory-bank/tech-debt.md.

4. Hermetic settings under pytest

engine/config/settings.py sets env_file=None when pytest is in sys.modules, so a developer's local .env cannot leak opt-in feature flags into the test suite.

Verification

1667 passed, 15 skipped, 56 xfailed
ruff check    — All checks passed
ruff format   — 18 files already formatted
contract scan — no violations

mypy engine/ reports one error (engine/inference_rule_registry.py:462 syntax) that reproduces on clean origin/main — pre-existing, not introduced here.

Deliberately out of scope

Made with Cursor

… pool

Two changes that cannot be split: the SDK chassis consumes the same
engine.handlers surface and the same GraphLifecycle that W4-04 modifies.

SDK-native chassis (dormant by default)
- chassis/entrypoint.py: single uvicorn target dispatching on L9_CHASSIS
  (legacy -> chassis_app.create_app, sdk -> node_app.create_app). Every
  launch site (Makefile, Dockerfile.prod, scripts/entrypoint.sh, compose)
  now points here, so switching chassis is config, not a command change.
- chassis/node_app.py: builds the app via constellation-node-sdk
  create_node_app. SdkLifecycleAdapter bridges engine.boot.GraphLifecycle
  (legacy LifecycleHook) onto the SDK's unrelated LifecycleHook ABC, which
  leaves engine/boot.py free of SDK imports during dual-run.
- chassis/handler_registration.py: registers ACTION_HANDLERS with the SDK
  registry, wrapping each with the PacketEnvelope audit side effect that
  chassis/actions.py applies on the legacy path.
- engine/handlers.py now exports ACTION_HANDLERS as the single action
  registry; chassis/actions.py consumes it instead of a hand-maintained
  dict, so the two chassis cannot drift. test_chassis_parity.py locks that.

W4-04 Postgres audit pool
- The ComplianceEngine consumer side is already on main; this adds the
  missing wiring. GraphLifecycle.startup creates an asyncpg pool when
  POSTGRES_DSN is set and passes it through init_dependencies to
  EngineState.db_pool; shutdown closes it. Soft dependency: an unset or
  unreachable DSN leaves db_pool None and logs a warning rather than
  blocking startup, matching the existing Neo4j degrade path.
- docker-compose gains a postgres service seeded from packet_store.sql.

Chassis consolidation
- Deletes chassis/app.py and chassis/auth/app.py, which duplicated
  chassis/chassis_app.py. All imports and launch sites repointed.

Settings
- Under pytest, env_file is None so a developer's local .env cannot leak
  opt-in flags into the suite.

Verified: 1667 passed / 15 skipped / 56 xfailed, ruff clean, contract
scanner clean. mypy reports one pre-existing syntax error on main.

L9_META headers are left at main's schema v1 so this does not collide
with the schema v2 stamp in #147.

Co-authored-by: Cursor <[email protected]>
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

PR Too Large
Reviewable lines changed: 1839
Limit: 1000 lines
Action Required: Break into smaller, atomic PRs

📋 Best Practices for Large Changes

  1. Refactoring + Features: Separate into 2 PRs
  2. Multiple Features: One PR per feature
  3. Database + Code: Separate migration from logic
  4. Generated Code: Exclude it from reviewable-size accounting

🚫 This PR is blocked until reviewable size limits are met.

ACTION_HANDLERS is now the single action->handler map for both chassis;
CONTRACT-02 and the compliance workflow comment still described the
pre-rename chassis/app.py layout.

- name: Set up Python
uses: actions/setup-python@v7
uses: actions/setup-python@v5
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
E Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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.

2 participants