Skip to content

rfc: provider-role policy membership - #1223

Draft
ragnorc wants to merge 2 commits into
ModernRelay:mainfrom
ragnorc:rfc/provider-role-policy-membership
Draft

ragnorc wants to merge 2 commits into
ModernRelay:mainfrom
ragnorc:rfc/provider-role-policy-membership

Conversation

@ragnorc

@ragnorc ragnorc commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Draft RFC: docs/rfcs/2026-11-01-provider-role-policy-membership.md, plus its registry row.

What it proposes

A policy group may name identity-provider role slugs as well as literal actor ids:

groups:
  owners: ["principal:01JD8Y3T2Z"]          # list form, unchanged
  analysts:
    actors: ["principal:01JE4K9M1Q"]
    provider_roles: [analyst, data-steward]

A server started with --membership-snapshot FILE reads a bounded, revisioned, bound-to-root JSON document listing which roles each admitted actor currently holds, and treats the actor as a member of every group whose provider_roles intersect those roles. Credentials stay identity-only; the OIDC admission snapshot is untouched; every action permission stays in applied policy. Without the flag, provider_roles match nobody and preview says so.

Scope

Membership only. Credential ceilings, client narrowing and Agent Auth are out of scope and would be separate RFCs. This replaces the membership half of #1218, which was closed after ModernRelay/og-control-plane#125 was closed in design review. The points raised there are addressed in the text:

  • Activation gap. The publisher lists every role every mapped actor holds, not only roles the applied policy references, so a policy that moves a group from role A to role B activates against a snapshot that already names B-holders. Preview reports role_unassigned, membership_unavailable and management_roles_only as warnings, not refusals.
  • Overflow. Bounds are counts (1,000 members, 8,000 role assignments) with a 2 MiB byte bound sized so any count-conforming file fits; the publisher refuses in full and reports which bound. The RFC states the consequence (role-derived membership lapses 330 s later) and why that beats a truncated file.
  • Freshness. The only native claim is that a fact observed at T is never used after T + 330 s. Provider propagation is the publisher's contract; the WorkOS behaviors (Directory Sync immediate, SSO at next sign-in, async role deletion, ordered Events API) are recorded as facts, not promises.
  • Outage and recovery are a table, including boot: a missing or misbound file refuses boot; a correctly bound but expired file serves literal membership only.

Verified against

origin/main f728f01: crates/omnigraph-policy (PolicyActorSelector { group }, groups as literal actor lists, Cedar entities compiled at load, unknown-actor denial before Cedar), crates/omnigraph-server/src/oidc_identity.rs (admission snapshot format, 300 s lifetime, 30 s skew, 5 s refresh), the identity RFC of 2026-09-09, /graphs/{graph_id}/access, and omnigraph policy validate/test/explain.

Groups may name identity-provider role slugs; role facts arrive through a
bounded, revisioned, 300-second membership snapshot read beside the OIDC
admission snapshot. Specifies evaluation, activation, overflow, outage and
recovery behavior. Replaces the membership half of the closed draft ModernRelay#1218.
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.

1 participant