Skip to content

api: split admin node_maintenance.rs by route family (pure move) - #568

Merged
ac-pplx merged 2 commits into
mainfrom
ac/split-api-admin-node-maintenance
Oct 16, 2026
Merged

ac-pplx merged 2 commits into
mainfrom
ac/split-api-admin-node-maintenance

Conversation

@ac-pplx

@ac-pplx ac-pplx commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

crates/libs/api/src/routes/admin/node_maintenance.rs (1,794 code lines) serves three admin route families besides the Direct node registry:

  • node status, health and reconcile;
  • node template pull and delete through the node-api, and listing from the cached template inventory;
  • the node-api client plumbing the registry and template routes use.

This keeps the registry handlers and the shared node types in node_maintenance.rs and moves the rest into three modules. node_maintenance.rs drops to 665 code lines; the largest new file is node_templates.rs at 509. Every line that touches a Direct-only table stays in the parent, so archcheck's direct_tables ratchet is unchanged.

This is a pure move, generated by scripts/split_rust_module.py (#562) from the spec below and proved by its verify. It is part of splitting the largest production modules into smaller ones with one job each.

What moved where

Module Holds Code lines
node_api Reaching a node's node-api from admin routes: endpoint normalization and verification, the client, and RPC error mapping. 175
node_status Admin node status, health and reconcile routes, and the cached node status they read. 466
node_templates Admin node template routes: pull and delete a template on a node through its node-api, and list a node's templates from the cached template inventory. 509
node_maintenance.rs (parent) the Direct node registry handlers, the shared node row and response types, node reads, and the default node publish they enqueue 665

How to check it

The spec (item names, not lines):

file = "crates/libs/api/src/routes/admin/node_maintenance.rs"

[[module]]
name = "node_api"
doc = "Reaching a node's node-api from admin routes: endpoint normalization and verification, the client, and RPC error mapping."
items = [
  "const NODE_API_CONNECT_TIMEOUT", "const NODE_API_FAST_RPC_TIMEOUT", "fn normalize_node_api_endpoint",
  "fn endpoint_uri", "fn node_endpoint", "fn proto_role_name", "fn bearer_kind_for_role",
  "fn verify_node_endpoint", "fn node_api_client", "fn node_rpc_error", "fn node_api_rpc_error_response",
]

[[module]]
name = "node_status"
doc = "Admin node status, health and reconcile routes, and the cached node status they read."
items = [
  "const DEFAULT_NODE_STATUS_CACHE_TTL_SECS", "struct NodeStatusRow", "struct ServiceHealthResponse",
  "struct ReconciliationStatusResponse", "struct NodeCtlStatusResponse", "struct NodeHealthStatusResponse",
  "struct RefreshNodeStatusRequest", "struct ReconcileFacetRequest", "struct ReconcileNodesRequest",
  "struct RefreshNodeStatusResponse", "struct ReconcileNodeResponse", "struct ReconcileNodesResponse",
  "struct ReconcileNodeNetworkPolicyResponse", "fn deserialize_reconcile_facet", "fn deserialize_reconcile_facets",
  "fn node_supports_state_reconciliation", "fn fetch_node_status_map", "fn node_status_refresh_needed",
  "fn fetch_cached_node_health", "fn default_node_publish_refs", "fn fetch_inventory_node",
  "fn reconcile_refs_from_request", "fn refresh_node_status", "fn reconcile_nodes", "fn node_health",
  "fn reconcile_node_network_policy",
]

[[module]]
name = "node_templates"
doc = "Admin node template routes: pull and delete a template on a node through its node-api, and list a node's templates from the cached template inventory."
items = [
  "const NODE_API_TEMPLATE_RPC_TIMEOUT", "const NODE_TEMPLATE_INVENTORY_CONCURRENCY",
  "struct NodeTemplateSnapshotResponse", "struct NodeTemplateInventoryRow", "struct NodeTemplateBuildResponse",
  "struct NodeTemplateInventoryResponse", "struct PullNodeTemplateRequest", "struct DeleteNodeTemplateQuery",
  "struct PullNodeTemplateResponse", "struct NodeFilters", "fn default_true", "fn non_empty_optional",
  "fn template_capable_node_role", "fn ensure_template_capable_node", "fn delete_cached_node_template_inventory", "fn note_node_template_deleted", "fn pull_node_template",
  "fn delete_node_template", "fn list_templates_for_node", "fn list_node_templates",
]

The tool is scripts/split_rust_module.py from #562 (not on main yet).

  • Regenerate: on main at b9fc395e0, run split_rust_module.py apply spec.toml && cargo fmt --all. This reproduces the first commit.
  • Proof: split_rust_module.py verify origin/main → regenerated and compared 4 files from 1 split parents: identical. verify derives the spec from the diff, regenerates the split from the merge base, and requires HEAD's Rust files to equal the rustfmt'd result byte for byte.
  • Edits inside moved text: 137 private items, fields or methods → pub(super). Each keeps the reach the item had: one module deeper, pub(super) reaches exactly the old module.

Observable changes

  • Log targets: 8 tracing events without an explicit target: now log under the new module paths (pplx_space_api::routes::admin::node_maintenance::<module> instead of pplx_space_api::routes::admin::node_maintenance). Nothing in the repository selects on these targets exactly.

  • sql! locators: the leading /*module:line*/ comments of 6 moved statements now name the new module path.

  • Comment: space-node-api-local/values.yaml cited pull_node_template in node_maintenance.rs; a docs commit points it at node_maintenance/node_templates.rs.

  • Diagnostics name new locations:

    • panic and backtrace locations of the 3 panic sites (expect, unwrap, unreachable!, asserts) in moved code name the new file and line;
    • the 1 panic site left in the parent shift line numbers;
    • the 8 tracing callsites in moved code report the new file and line in their metadata, including OpenTelemetry's code.filepath, code.lineno and code.namespace;
    • std::any::type_name of a moved type names its new module;
    • the 6 sql! locators that stay in the parent shift line numbers;

    The reviews found nothing in the repository that depends on these.

Validation

Run on a Linux development machine at the PR head:

  • cargo check --workspace --all-targets --all-features --locked: pass, no warnings.
  • Every clippy invocation in run_clippy_checks with -D warnings: pass.
  • cargo check -p pplx-space-api --no-default-features --all-targets: pass, with one unused-import warning at controllers/sandbox/mod.rs:1427 that main has too.
  • cargo nextest run -p pplx-space-api --all-features with Postgres, Redis and SPACE_CI_REQUIRE_TEST_DEPS=1: 1,827/1,827 passed with --run-ignored all (none skipped). The admin OpenAPI snapshot test passed unchanged.
  • archcheck as CI runs it: no required findings, and the same advisory count as main. node_maintenance.rs moves from listed_no_growth to a stale file_size entry.

Interactions

No open pull request touches node_maintenance.rs.

Follow-ups, kept out of this PR because verify allows no other Rust edits: comments in routes/admin/support.rs and controllers/substrate/direct.rs still cite node_maintenance.rs for moved handlers.

The archcheck file_size baseline entry for this file is now stale (an advisory finding). Split PRs leave that table alone, so they don't conflict with each other there; one follow-up prunes the stale entries after they land.

Rollback

Revert the commit(s). No data, configuration, wire or public API change.

🤖 Generated with Claude Code

@ac-pplx
ac-pplx force-pushed the ac/split-api-admin-node-maintenance branch from 1a61f75 to 123dfd6 Compare October 16, 2026 06:49
node_maintenance.rs serves three admin route families beside the Direct
node registry: node status, health and reconcile; node template pull and
delete through the node-api, and listing from the cached template
inventory; and the node-api client plumbing the registry and template
routes use. Keep the registry handlers, the shared node row and response
types, and the node reads in node_maintenance.rs, and move the rest into
child modules: node_api, node_status and node_templates.

Every line that touches a Direct-only table stays in
node_maintenance.rs, so archcheck's direct_tables ratchet is unchanged.

Generated by scripts/split_rust_module.py (#562) from the spec in the
pull request. Items move verbatim. The only edits keep each item's
reach: 137 private items, fields or methods become pub(super). The
parent re-exports the moved items, so no caller changes.
The Kind node-api chart comment cites pull_node_template by file. It now
lives in node_maintenance/node_templates.rs; require_admin_node_registry
stays in node_maintenance.rs.
@ac-pplx
ac-pplx force-pushed the ac/split-api-admin-node-maintenance branch from 123dfd6 to f90d4e1 Compare October 16, 2026 07:03
@ac-pplx
ac-pplx marked this pull request as ready for review October 16, 2026 14:49

@nickdujay-pplx nickdujay-pplx left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at f90d4e12b395b065d4bb0e49ad24f78c03798593; no blocking findings.

Verified all 93 original top-level items survive the split with their contents unchanged apart from the documented visibility adjustments and formatting. Checked public re-exports, route wiring, authorization/substrate guards, serde defaults and deserializers, RPC timeouts/error mapping, and SQL. The Helm values change is comments only.

Validation: reproduced the split across all 4 Rust files and ran the full API suite locally with real PostgreSQL and Redis, all features, and SPACE_CI_REQUIRE_TEST_DEPS=1: 1,826 passed, 0 skipped on macOS. Current CI is green, including all four Kind/Firecracker smoke shards.

No schema, configuration, or protocol migration is introduced, so this does not add a deployment-order or rollback dependency. The documented tracing-target and SQL/diagnostic-location changes remain; I found no exact old-target selectors in this repository.

@the-gigi-pplx

Copy link
Copy Markdown
Collaborator

Review

No findings.

Verified against f90d4e12b395b065d4bb0e49ad24f78c03798593.

What I ran:

  • scripts/split_rust_module.py verify origin/main, using the script from PR scripts: add split_rust_module.py for mechanical, verifiable Rust module splits #562's head: identical, exit 0.
  • apply with the spec in this PR's body, run on the merge base and rustfmt'd: it reproduces every .rs file at the head byte for byte. So the glob patterns in the published spec select the same items as the expanded spec verify --print-spec derives.
  • Each moved child file, grepped for self::/super:: in doc comments. The tool doesn't rewrite comments, so a link like that would point one module off after the move. There are none.
  • The non-split files, grepped for comments that name the old file next to a moved item.
  • Whether main has touched the split file since the merge base: it hasn't.

The non-Rust edits check out: pull_node_template is at node_maintenance/node_templates.rs:216, and require_admin_node_registry stays in node_maintenance.rs:192. The support.rs:205 pointer the body lists as a follow-up is still the only stale Rust comment I found.

What I didn't check: whether the grouping is the right one. That's a design call, and I took the body's word for it. I also didn't rebuild or retest the crate; CI is green on this head.

@the-gigi-pplx the-gigi-pplx left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. No findings; details in the review comment above.

@ac-pplx
ac-pplx added this pull request to the merge queue Oct 16, 2026
Merged via the queue into main with commit a88dd6b Oct 16, 2026
25 checks passed
@ac-pplx
ac-pplx deleted the ac/split-api-admin-node-maintenance branch October 16, 2026 16:41
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.

3 participants