Phase 2: Build state-aware tree iterator with boundary enforcement
## Overview
Extend `Gitlab::Database::NamespaceEachBatch` with state-aware boundary enforcement. The subclass (`Namespaces::StatePropagationIterator`) injects state filters into the recursive CTE's LATERAL subqueries so the DFS naturally skips subtrees whose root has an equal-or-higher-precedence propagated state. It also implements cursor rewind for mid-traversal boundary detection when a descendant's state changes concurrently.
## References
- [ADR 003: State Propagation Model — Boundary enforcement in the tree iterator](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/group_and_project_operations_and_state_management/decisions/003_state_propagation_model/)
- [Tree Iterator Documentation](https://docs.gitlab.com/development/database/poc_tree_iterator/)
- [`Gitlab::Database::NamespaceEachBatch`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/namespace_each_batch.rb)
- Parent epic: https://gitlab.com/groups/gitlab-org/-/epics/21607
## Exit Criteria
- [ ] `Namespaces::StatePropagationIterator` subclass exists and overrides `walk_down` and `next_elements` with state filter
- [ ] DFS traversal prunes subtrees at propagation boundaries (higher-precedence states)
- [ ] Cursor rewind logic correctly handles mid-traversal concurrent state changes
- [ ] Iterator resumes from the boundary's next sibling after rewind
- [ ] All specs pass, covering basic traversal, boundary skipping, cursor rewind, and large hierarchies
epic