5.4 KiB
TODOS
SCIM
Config-gated denial tests (SCIM_ENABLED=false, ORG_GROUPS_ENABLED=false)
What: Test the two config master switches from the denied side: a valid token
against SCIM_ENABLED=false must get the uniform 401, and any Groups route with
ORG_GROUPS_ENABLED=false must get the SCIM-enveloped 501.
Why: These are the primary kill switches for the whole surface and the one authz-matrix case the build plan promised that is still missing.
Context: CONFIG is a process-global LazyLock pinned by the test-support
#[ctor] before main, so the disabled states cannot be tested in the same
process as the enabled suite. Needs either a second test binary with its own
ctor env, or an injectable check in guard.rs / groups.rs. See the
plan-delivery-gap-scim-disabled-authz-case learning.
Effort: M Priority: P1 Depends on: None
Live Entra ID tenant validation
What: Run the full lifecycle against a throwaway Entra tenant: Test Connection, assign user, create/update/deprovision/restore, group sync, token rotation. Follow docs/scim/README.md as written and fix any doc drift found.
Why: Everything is verified against RFC 7643/7644 and observed Entra behaviour, but no real Entra sync has run against this build yet.
Context: User-driven (needs a tenant). Never production. The rate limiter
keys on IP_HEADER (X-Real-IP) - the deployment in front must set it.
Effort: M Priority: P1 Depends on: Branch pushed and deployed somewhere TLS-fronted
Mail-enabled invite failure path, end to end
What: An integration test that runs post_user with mail enabled and a
failing SMTP target, asserting the 500 plus the rollback outcome.
Why: The rollback decision logic is unit-tested
(provisioning_rollback_spares_preexisting_users), but the branch that calls it
(send_invite failure inside post_user) still never executes under test.
Context: Needs mail enabled in CONFIG (same process-global constraint as
above) plus a fast-failing SMTP endpoint; naive versions are slow or flaky.
Consider folding into the same second test binary as the config-gated tests.
Effort: M Priority: P2 Depends on: Config-gated denial tests (shared harness)
Coverage: error-envelope edges and manage HTTP surface
What: Tests for the remaining actionable gaps from the ship coverage audit (82%): malformed-body 400 / oversized-body 413 envelopes, HTTP-level 429 envelope, POST /Users missing/invalid email 400s, policy-blocked restore 400, GroupPatch path-less object form (Entra sends this shape), externalId HTTP filters, POST /Groups blank-name 400 and dup-externalId 409, and the manage endpoints driven over HTTP with AdminHeaders.
Why: These are the branches where a regression would surface to Entra as a wrong status code or envelope, currently proven only by adjacent coverage.
Context: All testable in the existing Rocket-local harness except the manage endpoints, which need an AdminHeaders fixture. Coverage map in the 2026-07-19 ship PR body has the full gap list.
Effort: M Priority: P2 Depends on: None
Performance backlog for large orgs
What: SQL-side pagination for /Users and /Groups lists, batched group
member writes (resolve via eq_any, diff instead of delete-all+reinsert on
PUT), and secondary indexes on users_organizations(org_uuid, external_id) and
groups(organizations_uuid, external_id).
Why: Current implementation loads full member/group sets per list request and issues ~4N queries for an N-member group write. Fine at self-host scale (hundreds of members); wasteful for thousands.
Context: Indexes diverge from upstream's no-secondary-index convention - decide deliberately. Review findings from 2026-07-19 have the details.
Effort: L Priority: P3 Depends on: None
Harden SCIM write edges surfaced by adversarial review
What: Three lower-severity robustness gaps from the 2026-07-19 adversarial
pass: (1) externalId uniqueness is check-then-set with no backing DB unique
index, so concurrent writes could duplicate the correlation key; (2) a Group
displayName > 100 chars or externalId > 300 chars from Entra hits the MySQL
column limit and returns a 500 instead of a 400 invalidValue; (3) scim_status
returns key metadata behind only an AdminHeaders session with no password/OTP
re-auth, unlike generate/delete.
Why: None are exploitable today (single Entra sync engine; strict-mode MySQL only; admin session required), but each is an unenforced invariant or an inconsistent guard that a future change could turn into a real bug.
Why not now: (1) wants a migration adding a partial unique index across three dialects - real schema work, deferrable; (2) wants length validation in the Group handlers; (3) is a one-line guard tightening. Bundle them.
Effort: M Priority: P2 Depends on: None
Upstream hygiene
ip_constant clippy lints in http_client.rs tests
What: 9 pre-existing clippy::ip_constant errors in upstream
src/http_client.rs test code under --all-targets with the 1.96 toolchain.
Why: Blocks running cargo clippy --all-targets clean locally; will bite
if CI ever lints test targets.
Context: Upstream code, untouched per branch discipline. Fix as a separate
commit or PR upstream (Ipv4Addr::LOCALHOST instead of hand-coded addresses).
Effort: S Priority: P3 Depends on: None