SCIM: users, groups, queries, PATCH, Bulk and cursors at /scim/v2, over x:Account (SCIM-1 to SCIM-57)

Every SCIM operation becomes the x:Account get, query or set JMAP makes,
as the service principal, so permissions, tenant scope and limits,
address uniqueness and account destruction are enforced in one place.
Discovery is anonymous; everything else takes an API key as a bearer
token and nothing else. Domains open to SCIM carry a flag in the domain
cache. Filters take eq and and, answered from the account indexes, with
unindexed attributes checked on at most 200 candidates. Cursors are
stateless, HMAC-sealed under the server key. PATCH applies to the
resource in memory and saves it as a PUT, so it is all or nothing.
Groups get an address from their display name on the principal's
domain; membership is written on each user.

Every write emits one of five new scim.* events (ids 637 to 641), also
added to the packaged schema. The helpers the surviving SCIM suites
import are rebuilt from the spec; scim_tests runs the new acceptance
suite and the surviving tenant isolation suite, and both pass.
This commit is contained in:
2026-09-19 09:35:23 -07:00
parent 776d18d06e
commit 0ca26070d7
28 changed files with 6141 additions and 22 deletions
+6
View File
@@ -478,6 +478,12 @@ impl ParseHttp for Server {
return crate::branding::rsvp_page(self, RSVP_PAGE).await;
}
}
// inbuxa: SCIM 2.0 provisioning (feature 7)
"scim" => {
if path.next() == Some("v2") {
return Ok(crate::scim::handle(self, &mut req, &session).await);
}
}
// inbuxa: BT-5: the logo that applies, anonymous
"logo" if req.method() == Method::GET => {
self.is_http_anonymous_request_allowed(session.remote_ip)