Description
PR #735 made facade_for walk owner and parent links, but PR #733 P2.1/P2.11 are not fully closed. Unresolvable limiters remain silently accepted, MS DHCP-security/link-aggregation fan-outs still depend on transient LogContext state, and _resolve_org_id in core/api_facade.py:158-172 guesses that any 18-character first argument is an organization ID. Make pacing ownership explicit and loud, carry org_id through the affected fan-outs, and remove identifier-shape guessing that can key a network as an organization.
Acceptance Criteria
- #1 Every production facade owner resolves a non-None rate limiter or fails loudly before an unpaced call
- #2 MS DHCP-security and link-aggregation calls acquire the configured organization bucket
- #3 Network IDs cannot be inferred as organization IDs from string length
- #4 A tree-level regression check covers facade routing without relying on one fragile AST spelling
Definition of Done
- #1 make check (uv run ruff check . && uv run ruff format –check . && uv run mypy . && uv run pytest -v)
- #2 make docgen, when metrics, config, endpoints or collectors changed — CI fails the build on generated-docs drift
- #3 Grafana queries in grafana/dashboards/*.json and grafana/alerts/ updated, if a metric or label name changed
Implementation Plan
Wave 1 L2: jointly resolve explicit organization pacing with MDE-0014 across the API facade seam; child owns local edits and focused validation, root owns integration and final gate.
Final Summary
Implemented and verified in 7327153. Facade pacing fails closed and preserves explicit organization scope; full gates passed.