Skip to content

refactor!: collapse create_session proof type into session x create#866

Open
kilianglas wants to merge 16 commits into
kilianglas/uniqueness-session-binding-contractsfrom
kilianglas/collapse-create-session
Open

refactor!: collapse create_session proof type into session x create#866
kilianglas wants to merge 16 commits into
kilianglas/uniqueness-session-binding-contractsfrom
kilianglas/collapse-create-session

Conversation

@kilianglas

@kilianglas kilianglas commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Removes ProofType::CreateSession and redesigns the request model: proof_type shrinks to {uniqueness, session} and session_id becomes a three-state field. Creating a session was always create-and-prove (a session proof in the same response), so it collapses into proof_type: "session" + session_id: "create" with no capability change. Hence, there are only two proof types now, Uniqueness Proofs and Session Proofs. Both can create a session, or be bound to an existing session. Therefore, sessions can either be bound to a nullifier, or can be started without any binding. Note, that Uniquess Proofs can still be requested without creating or binding a session.

Stacked on #862.

Request model

New SessionRef type carried by ProofRequest.session_id:

wire value state
absent / null SessionRef::None
"create" SessionRef::Create — mint a fresh session, prove it in the same response
"session_<hex>" SessionRef::Existing(SessionId)

Note: The SessionRef is not in the signed part of the request.

Validation matrix (validate_proof_type):

null "create" "session_<hex>"
uniqueness ✅ plain ✅ create bound session ✅ bind-existing
session ✅ (was create_session)

action remains forbidden for proof_type: "session" (both sub-states).

Different combinations have different use cases:

  • uniqueness, null: Standalone uniqueness proof that does not require session.
  • uniqueness, "create": Uniqueness proof that requires bound session for later session proof.
  • uniqueness, "session_<hex>": Uniqueness proof that is bound to existing session. The need for this mode is less obvious. But seems to be useful once OPRF key rotation is implemented.
  • session, "create": Create new standalone session to prove human continuity without uniqueness guarantees. Used e.g., in the upcoming DeepFace proof type.
  • session, "session_<hex>": Session proof for existing session. This is used for any session_id, uniqueness bound or not.

Changes to OPRF nodes

To make this work, the auth module of the ORPF nodes had to be slightly changed. OPRF queries with prefix 0x01 (used to obtain the session seed), can now originate from Uniqueness Proof RP requests. Those have an action field iin the signed data. Hence, in order to verify the RP Request signature, the OPRF request needs to carry this action, which differs from action = oprf_seed which is used for the query. We introduce a new field called rp_signature_verification on NullifierOprfRequestAuthV1 struct.

WIP-101 RPs

Important: Combined uniqueness + create session requests are not yet supported. This will be implemented in a follow-up PR.

kilianglas and others added 5 commits July 14, 2026 15:18
Replace the dedicated create-session proof type with a three-state session reference so request semantics are explicit on the wire.

Co-authored-by: Cursor <cursoragent@cursor.com>
Carry the RP-signed uniqueness action separately from the session OPRF seed so nodes can safely authorize atomic session creation.

Co-authored-by: Cursor <cursoragent@cursor.com>
Accept create and existing session references on uniqueness requests, mint sessions through the authenticator, and validate the corresponding response semantics.

Co-authored-by: Cursor <cursoragent@cursor.com>
Exercise the signed-action create flow end to end and generate verifier fixtures from a session minted by the uniqueness request.

Co-authored-by: Cursor <cursoragent@cursor.com>
Document create, existing, and unbound uniqueness modes together with the signed-action OPRF flow and deployment order.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kilianglas
kilianglas force-pushed the kilianglas/collapse-create-session branch from 5fee2df to f651855 Compare July 14, 2026 13:25
Comment on lines +339 to +341
fn visit_unit<E: serde::de::Error>(self) -> Result<Self::Value, E> {
Ok(SessionRef::None)
}

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.

Is visit unit needed? The serializer does not actually use it?

Comment on lines +225 to +226
SessionRef::None => {
unreachable!("SessionRef::None should be handled by the guard above")

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.

why not move the above if block in here then?

/// required (see [`Self::binds_session`]).
/// The proof will only be valid if the session ID is meant for this context and
/// this particular World ID holder.
pub session_id: Option<SessionId>,

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.

An old request might actually parse as a SessionRef::Existing here, depending on how the autogenerated serde derive handles the option here. I guess this is fine though and maybe even wanted?

/// If omitted, the request is strictly treated as a [`ProofType::Uniqueness`] request.
/// Session creation and session proving must opt in explicitly.
#[serde(default)]
pub proof_type: ProofType,

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.

Old create_session requests will now fail for sure though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes. @paolodamico is this an issue?

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