Documentation
¶
Overview ¶
Package sessionstate defines the durable browser-session ownership and persistence contracts.
Index ¶
- Constants
- Variables
- func NormalizeConsentScopes(scopes []string) ([]string, error)
- func RedisClusterHashTag(key string) string
- type AssuranceSummary
- type BackendAffinitySummary
- type CeremonyRecord
- type Clock
- type CommitRequest
- type ConsentGrant
- type Contract
- type DeleteRequest
- type EnrollmentRecord
- type Event
- type EventKind
- type Handle
- type HandleGenerator
- type IdentitySummary
- type Invariant
- type Keyspace
- type LegacyCookieItem
- type LogoutIndex
- type Metrics
- type OIDCFlow
- type OIDCFlowRepository
- type OwnedReference
- type Owner
- type RandomHandleGenerator
- type Record
- type RedisRepository
- func (r *RedisRepository[T]) Commit(ctx context.Context, request CommitRequest[T]) (Revision, error)
- func (r *RedisRepository[T]) Consume(ctx context.Context, request DeleteRequest) (Versioned[T], error)
- func (r *RedisRepository[T]) Delete(ctx context.Context, request DeleteRequest) error
- func (r *RedisRepository[T]) Load(ctx context.Context, reference Reference) (Versioned[T], error)
- type RedisStoreConfig
- type RedisStores
- func (s *RedisStores) Commit(ctx context.Context, request TransactionRequest) (TransactionReceipt, error)
- func (s *RedisStores) CommitCeremony(ctx context.Context, request CommitRequest[CeremonyRecord]) (Revision, error)
- func (s *RedisStores) CommitEnrollment(ctx context.Context, request CommitRequest[EnrollmentRecord]) (Revision, error)
- func (s *RedisStores) CommitLogoutIndex(ctx context.Context, request CommitRequest[LogoutIndex]) (Revision, error)
- func (s *RedisStores) CommitOIDCFlow(ctx context.Context, request CommitRequest[OIDCFlow]) (Revision, error)
- func (s *RedisStores) CommitSAMLFlow(ctx context.Context, request CommitRequest[SAMLFlow]) (Revision, error)
- func (s *RedisStores) CommitSelfServiceFlow(ctx context.Context, request CommitRequest[SelfServiceFlow]) (Revision, error)
- func (s *RedisStores) CommitStepUp(ctx context.Context, request CommitRequest[StepUpRecord]) (Revision, error)
- func (s *RedisStores) CommitTOTPRecovery(ctx context.Context, request CommitRequest[TOTPRecoveryRecord]) (Revision, error)
- func (s *RedisStores) ConsumeCeremony(ctx context.Context, request DeleteRequest) (Versioned[CeremonyRecord], error)
- func (s *RedisStores) ConsumeOIDCFlow(ctx context.Context, request DeleteRequest) (Versioned[OIDCFlow], error)
- func (s *RedisStores) ConsumeSAMLFlow(ctx context.Context, request DeleteRequest) (Versioned[SAMLFlow], error)
- func (s *RedisStores) ConsumeSelfServiceFlow(ctx context.Context, request DeleteRequest) (Versioned[SelfServiceFlow], error)
- func (s *RedisStores) ConsumeStepUp(ctx context.Context, request DeleteRequest) (Versioned[StepUpRecord], error)
- func (s *RedisStores) DeleteEnrollment(ctx context.Context, request DeleteRequest) error
- func (s *RedisStores) DeleteLogoutIndex(ctx context.Context, request DeleteRequest) error
- func (s *RedisStores) DeleteOIDCFlow(ctx context.Context, request DeleteRequest) error
- func (s *RedisStores) DeleteSAMLFlow(ctx context.Context, request DeleteRequest) error
- func (s *RedisStores) DeleteSelfServiceFlow(ctx context.Context, request DeleteRequest) error
- func (s *RedisStores) DeleteStepUp(ctx context.Context, request DeleteRequest) error
- func (s *RedisStores) DeleteTOTPRecovery(ctx context.Context, request DeleteRequest) error
- func (s *RedisStores) RevokeSession(ctx context.Context, request RevocationRequest) error
- func (s *RedisStores) TouchSession(ctx context.Context, reference Reference, idleTTL time.Duration) (bool, error)
- type Reference
- type Repository
- type Revision
- type RevocationRequest
- type SAMLFlow
- type SAMLFlowRepository
- type SelfServiceFlow
- type SelfServiceFlowRepository
- type SessionAnchor
- type SessionRepository
- type StepUpRecord
- type TOTPRecoveryRecord
- type Transaction
- type TransactionFactory
- type TransactionReceipt
- type TransactionRequest
- type Versioned
Constants ¶
const EncodedHandleLength = 43
EncodedHandleLength is the unpadded base64url length of a 256-bit handle.
const LegacyCookieKeyCount = 84
LegacyCookieKeyCount is the audited number of legacy primary-cookie fields.
Variables ¶
var ( ErrNotFound = errors.New("session record not found") ErrRevisionConflict = errors.New("session record revision conflict") ErrParentMissing = errors.New("session record parent missing") ErrBindingMismatch = errors.New("session record binding mismatch") ErrExpired = errors.New("session record expired") ErrRevoked = errors.New("session record revoked") ErrInvalidTTL = errors.New("session record invalid TTL") ErrActiveFlowLimit = errors.New("session active flow limit reached") )
Store errors are stable fail-closed classifications for callers and tests.
Functions ¶
func NormalizeConsentScopes ¶
NormalizeConsentScopes returns one deterministic bounded scope set for persistence.
func RedisClusterHashTag ¶
RedisClusterHashTag returns the explicit cluster hash tag from a derived key.
Types ¶
type AssuranceSummary ¶
type AssuranceSummary struct {
Level int
Method string
Scope string
ProvenAt time.Time
ExpiresAt time.Time
}
AssuranceSummary is the stable, non-secret MFA assurance shared by protocol flows.
type BackendAffinitySummary ¶
type BackendAffinitySummary struct {
Type string
Name string
Protocol string
Authority string
OpaqueToken string
}
BackendAffinitySummary binds follow-up operations to an authority backend without browser exposure.
type CeremonyRecord ¶
type CeremonyRecord struct {
Record
Session Handle
Flow Handle
IdentityReference string
Protocol string
Kind string
Attempt uint64
Payload json.RawMessage
ConsumedAt time.Time
}
CeremonyRecord owns one short-lived single-use WebAuthn operation.
type CommitRequest ¶
type CommitRequest[T any] struct { Reference Reference ExpectedRevision Revision Value T TTL time.Duration }
CommitRequest describes one typed revision-checked write without prescribing a Redis encoding.
type ConsentGrant ¶
type ConsentGrant struct {
Record
IdentityReference string
ClientID string
Scopes []string
GrantedAt time.Time
GrantExpiresAt time.Time
}
ConsentGrant is one longer-lived OIDC consent bound to a stable identity and client.
type Contract ¶
Contract maps an invariant to the future runtime and test owners.
func ContractFor ¶
ContractFor returns the executable ownership mapping for one invariant.
type DeleteRequest ¶
DeleteRequest describes one revision-checked cleanup operation.
type EnrollmentRecord ¶
type EnrollmentRecord struct {
Record
Session Handle
Flow Handle
AccountReference string
IdentityReference string
RequiredMethods []string
CompletedMethods []string
CurrentStep string
Continuation string
Completed bool
}
EnrollmentRecord owns one required-factor enrollment state machine.
type EventKind ¶
type EventKind string
EventKind is a bounded identifier-free session telemetry classification.
const ( EventLoadFailure EventKind = "load_failure" EventCommitFailure EventKind = "commit_failure" EventCleanupFailure EventKind = "cleanup_failure" EventFormatRejection EventKind = "format_rejection" EventSafeRestart EventKind = "safe_restart" )
Event kinds are the complete bounded telemetry outcome vocabulary.
type Handle ¶
type Handle string
Handle is an opaque, non-semantic reference to one server-side record.
func ParseHandle ¶
ParseHandle validates and returns one canonical 256-bit opaque handle.
type HandleGenerator ¶
HandleGenerator creates cryptographically random opaque references.
type IdentitySummary ¶
IdentitySummary is the bounded, non-secret authenticated identity projection used by browser flows.
type Invariant ¶
type Invariant string
Invariant names one architecture property that must remain executable.
const ( InvariantEnvelopeSize Invariant = "envelope_size" InvariantServerSideOwnership Invariant = "server_side_ownership" InvariantCrossFlowBinding Invariant = "cross_flow_binding" InvariantProtocolCoexistence Invariant = "protocol_coexistence" InvariantCompareAndSwap Invariant = "compare_and_swap" InvariantExpiry Invariant = "expiry" InvariantFormatRejection Invariant = "format_rejection" InvariantSafeRestart Invariant = "safe_checkpoint_restart" InvariantUniformVersion Invariant = "uniform_version_rollout" InvariantFailureAtomicity Invariant = "failure_atomicity" )
Invariants are the executable durable browser-session architecture properties.
type Keyspace ¶
type Keyspace struct {
// contains filtered or unexported fields
}
Keyspace derives non-disclosing Redis Cluster keys from opaque handles.
func NewKeyspace ¶
NewKeyspace creates a keyed-digest namespace for durable browser-session records.
type LegacyCookieItem ¶
LegacyCookieItem gives one legacy field exactly one future persistence owner.
func LegacyCookieInventory ¶
func LegacyCookieInventory() []LegacyCookieItem
LegacyCookieInventory returns the complete audited primary-cookie ownership map.
type LogoutIndex ¶
type LogoutIndex struct {
Record
Session Handle
IdentityReference string
Account string
OIDCClientIDs []string
}
LogoutIndex is the bounded per-browser list of issued OIDC client sessions. It is current-v1 session-owned state and never contains tokens or browser data.
type Metrics ¶
type Metrics interface {
Observe(event Event)
}
Metrics records bounded session lifecycle outcomes.
type OIDCFlow ¶
type OIDCFlow struct {
Record
Session Handle
ParentFlow Handle
FlowType string
CurrentStep string
AuthOutcome string
CancelTarget string
ReturnTarget string
ResumeTarget string
CreatedAt time.Time
UpdatedAt time.Time
PendingMFA bool
ClientID string
RedirectURI string
ResponseType string
GrantType string
DeviceCode string
DeviceUserCodeDigest string
Scopes []string
State string
Nonce string
Prompt string
CodeChallenge string
CodeChallengeMethod string
ConsentChallenge string
ConsentDecision string
DelayedResponse bool
Authenticated bool
AssuranceSatisfied bool
Issuable bool
Issued bool
Consumed bool
}
OIDCFlow identifies one isolated OIDC flow record.
type OIDCFlowRepository ¶
type OIDCFlowRepository interface {
Repository[OIDCFlow]
}
OIDCFlowRepository persists OIDC request and response state independently from SAML.
type OwnedReference ¶
OwnedReference names a typed child key without exposing its raw handle externally.
type Owner ¶
type Owner string
Owner is the sole future persistence owner of legacy browser-session state.
const ( OwnerEnvelope Owner = "envelope" OwnerSessionAnchor Owner = "session_anchor" OwnerOIDCFlow Owner = "oidc_flow" OwnerSAMLFlow Owner = "saml_flow" OwnerSelfServiceFlow Owner = "self_service_flow" OwnerEnrollment Owner = "required_mfa_enrollment" OwnerStepUp Owner = "step_up" OwnerWebAuthnCeremony Owner = "webauthn_ceremony" OwnerTOTPRecovery Owner = "totp_recovery" OwnerConsent Owner = "consent_logout_indexes" OwnerProtocolSession Owner = "protocol_session" OwnerDeletion Owner = "deletion" )
Owner values name the exclusive durable owner for each legacy field.
type RandomHandleGenerator ¶
type RandomHandleGenerator struct {
// contains filtered or unexported fields
}
RandomHandleGenerator creates 256-bit opaque handles from a supplied entropy source.
func NewRandomHandleGenerator ¶
func NewRandomHandleGenerator(reader io.Reader) *RandomHandleGenerator
NewRandomHandleGenerator creates a handle generator and defaults nil entropy to crypto/rand.Reader.
func (*RandomHandleGenerator) NewHandle ¶
func (g *RandomHandleGenerator) NewHandle() (Handle, error)
NewHandle returns one URL-safe 256-bit opaque handle.
type RedisRepository ¶
type RedisRepository[T any] struct { // contains filtered or unexported fields }
RedisRepository persists one typed record family under an exclusive owner namespace.
func (*RedisRepository[T]) Commit ¶
func (r *RedisRepository[T]) Commit(ctx context.Context, request CommitRequest[T]) (Revision, error)
Commit atomically creates or compare-and-swap updates one typed record.
func (*RedisRepository[T]) Consume ¶
func (r *RedisRepository[T]) Consume(ctx context.Context, request DeleteRequest) (Versioned[T], error)
Consume atomically returns and deletes one record at the expected revision. Callers must not expose the value unless this operation succeeds.
func (*RedisRepository[T]) Delete ¶
func (r *RedisRepository[T]) Delete(ctx context.Context, request DeleteRequest) error
Delete removes one record only when the expected revision still matches.
type RedisStoreConfig ¶
RedisStoreConfig defines namespace and write-amortization policy for typed stores.
type RedisStores ¶
type RedisStores struct {
Session *RedisRepository[SessionAnchor]
OIDC *RedisRepository[OIDCFlow]
SAML *RedisRepository[SAMLFlow]
SelfService *RedisRepository[SelfServiceFlow]
Enrollment *RedisRepository[EnrollmentRecord]
StepUp *RedisRepository[StepUpRecord]
Ceremony *RedisRepository[CeremonyRecord]
TOTPRecovery *RedisRepository[TOTPRecoveryRecord]
Consent *RedisRepository[ConsentGrant]
Logout *RedisRepository[LogoutIndex]
// contains filtered or unexported fields
}
RedisStores groups separately keyed typed repositories that share one cluster keyspace.
func NewRedisStores ¶
func NewRedisStores( client redis.UniversalClient, digestSecret []byte, clock Clock, config RedisStoreConfig, ) (*RedisStores, error)
NewRedisStores creates the complete typed repository set without activating browser paths.
func (*RedisStores) Commit ¶
func (s *RedisStores) Commit(ctx context.Context, request TransactionRequest) (TransactionReceipt, error)
Commit atomically applies a revision-checked typed mutation set in one Redis Cluster slot.
func (*RedisStores) CommitCeremony ¶
func (s *RedisStores) CommitCeremony(ctx context.Context, request CommitRequest[CeremonyRecord]) (Revision, error)
CommitCeremony atomically indexes and commits one short-lived WebAuthn operation.
func (*RedisStores) CommitEnrollment ¶
func (s *RedisStores) CommitEnrollment(ctx context.Context, request CommitRequest[EnrollmentRecord]) (Revision, error)
CommitEnrollment atomically indexes and commits one required-factor enrollment.
func (*RedisStores) CommitLogoutIndex ¶
func (s *RedisStores) CommitLogoutIndex(ctx context.Context, request CommitRequest[LogoutIndex]) (Revision, error)
CommitLogoutIndex atomically indexes and commits the current-v1 browser logout record.
func (*RedisStores) CommitOIDCFlow ¶
func (s *RedisStores) CommitOIDCFlow(ctx context.Context, request CommitRequest[OIDCFlow]) (Revision, error)
CommitOIDCFlow atomically adds one bounded OIDC index entry and commits its typed child.
func (*RedisStores) CommitSAMLFlow ¶
func (s *RedisStores) CommitSAMLFlow(ctx context.Context, request CommitRequest[SAMLFlow]) (Revision, error)
CommitSAMLFlow atomically adds one bounded SAML index entry and commits its typed child.
func (*RedisStores) CommitSelfServiceFlow ¶
func (s *RedisStores) CommitSelfServiceFlow( ctx context.Context, request CommitRequest[SelfServiceFlow], ) (Revision, error)
CommitSelfServiceFlow atomically indexes and commits one bounded internal-login flow.
func (*RedisStores) CommitStepUp ¶
func (s *RedisStores) CommitStepUp(ctx context.Context, request CommitRequest[StepUpRecord]) (Revision, error)
CommitStepUp atomically indexes and commits one dynamic-assurance operation.
func (*RedisStores) CommitTOTPRecovery ¶
func (s *RedisStores) CommitTOTPRecovery(ctx context.Context, request CommitRequest[TOTPRecoveryRecord]) (Revision, error)
CommitTOTPRecovery atomically indexes and commits one TOTP or recovery operation.
func (*RedisStores) ConsumeCeremony ¶
func (s *RedisStores) ConsumeCeremony( ctx context.Context, request DeleteRequest, ) (Versioned[CeremonyRecord], error)
ConsumeCeremony atomically removes a ceremony and its bounded anchor index before returning the payload.
func (*RedisStores) ConsumeOIDCFlow ¶
func (s *RedisStores) ConsumeOIDCFlow( ctx context.Context, request DeleteRequest, ) (Versioned[OIDCFlow], error)
ConsumeOIDCFlow atomically removes one OIDC flow and its bounded anchor index before returning the payload.
func (*RedisStores) ConsumeSAMLFlow ¶
func (s *RedisStores) ConsumeSAMLFlow( ctx context.Context, request DeleteRequest, ) (Versioned[SAMLFlow], error)
ConsumeSAMLFlow atomically removes one SAML flow and its bounded anchor index before returning the payload.
func (*RedisStores) ConsumeSelfServiceFlow ¶
func (s *RedisStores) ConsumeSelfServiceFlow( ctx context.Context, request DeleteRequest, ) (Versioned[SelfServiceFlow], error)
ConsumeSelfServiceFlow atomically removes one internal-login flow and its bounded anchor index.
func (*RedisStores) ConsumeStepUp ¶
func (s *RedisStores) ConsumeStepUp( ctx context.Context, request DeleteRequest, ) (Versioned[StepUpRecord], error)
ConsumeStepUp atomically removes one terminal step-up and its bounded anchor index.
func (*RedisStores) DeleteEnrollment ¶
func (s *RedisStores) DeleteEnrollment(ctx context.Context, request DeleteRequest) error
DeleteEnrollment atomically removes one enrollment child and its anchor index entry.
func (*RedisStores) DeleteLogoutIndex ¶
func (s *RedisStores) DeleteLogoutIndex(ctx context.Context, request DeleteRequest) error
DeleteLogoutIndex atomically removes one logout index and its anchor entry.
func (*RedisStores) DeleteOIDCFlow ¶
func (s *RedisStores) DeleteOIDCFlow(ctx context.Context, request DeleteRequest) error
DeleteOIDCFlow atomically removes one OIDC child and its anchor index entry.
func (*RedisStores) DeleteSAMLFlow ¶
func (s *RedisStores) DeleteSAMLFlow(ctx context.Context, request DeleteRequest) error
DeleteSAMLFlow atomically removes one SAML child and its anchor index entry.
func (*RedisStores) DeleteSelfServiceFlow ¶
func (s *RedisStores) DeleteSelfServiceFlow(ctx context.Context, request DeleteRequest) error
DeleteSelfServiceFlow atomically removes one internal-login child and its anchor index entry.
func (*RedisStores) DeleteStepUp ¶
func (s *RedisStores) DeleteStepUp(ctx context.Context, request DeleteRequest) error
DeleteStepUp atomically removes one step-up child and its anchor index entry.
func (*RedisStores) DeleteTOTPRecovery ¶
func (s *RedisStores) DeleteTOTPRecovery(ctx context.Context, request DeleteRequest) error
DeleteTOTPRecovery atomically removes one TOTP/recovery child and its anchor index entry.
func (*RedisStores) RevokeSession ¶
func (s *RedisStores) RevokeSession(ctx context.Context, request RevocationRequest) error
RevokeSession writes the anchor tombstone before best-effort idempotent child deletion.
func (*RedisStores) TouchSession ¶
func (s *RedisStores) TouchSession( ctx context.Context, reference Reference, idleTTL time.Duration, ) (bool, error)
TouchSession refreshes idle expiry only after the configured write-amortization window.
type Repository ¶
type Repository[T any] interface { Load(ctx context.Context, reference Reference) (Versioned[T], error) Commit(ctx context.Context, request CommitRequest[T]) (Revision, error) Delete(ctx context.Context, request DeleteRequest) error }
Repository is the revision-aware persistence boundary for one typed record family.
type Revision ¶
type Revision uint64
Revision is the monotonic compare-and-swap revision of a server-side record.
type RevocationRequest ¶
type RevocationRequest struct {
Reference Reference
ExpectedRevision Revision
TombstoneTTL time.Duration
Children []OwnedReference
RejectRevoked bool
}
RevocationRequest defines a tombstone-first session and child cleanup operation.
type SAMLFlow ¶
type SAMLFlow struct {
Record
Session Handle
ParentFlow Handle
FlowType string
CurrentStep string
AuthOutcome string
CancelTarget string
ReturnTarget string
CreatedAt time.Time
UpdatedAt time.Time
PendingMFA bool
EntityID string
RequestID string
RequestDigest string
RelayState string
Destination string
OriginalURL string
ResumeTarget string
Logout bool
DelayedResponse bool
Authenticated bool
EnrollmentComplete bool
AssuranceSatisfied bool
Issuable bool
Issued bool
Consumed bool
}
SAMLFlow identifies one isolated SAML flow record.
type SAMLFlowRepository ¶
type SAMLFlowRepository interface {
Repository[SAMLFlow]
}
SAMLFlowRepository persists SAML request and response state independently from OIDC.
type SelfServiceFlow ¶
type SelfServiceFlow struct {
FlowType string
CurrentStep string
AuthOutcome string
LoginTarget string
ResumeTarget string
Record
Session Handle
CreatedAt time.Time
UpdatedAt time.Time
}
SelfServiceFlow identifies one internal primary-login flow for the MFA portal.
type SelfServiceFlowRepository ¶
type SelfServiceFlowRepository interface {
Repository[SelfServiceFlow]
}
SelfServiceFlowRepository persists internal browser-login state independently from external protocols.
type SessionAnchor ¶
type SessionAnchor struct {
Record
SchemaVersion uint8
CreatedAt time.Time
IdleExpiresAt time.Time
AbsoluteExpiresAt time.Time
LastTouchedAt time.Time
Authenticated bool
IdentityReference string
Identity IdentitySummary
BackendAffinity BackendAffinitySummary
MFAIdentityReference string
MFAIdentity IdentitySummary
MFABackendAffinity BackendAffinitySummary
Assurance AssuranceSummary
RotatedFrom Handle
OIDCFlows []Handle
SAMLFlows []Handle
SelfServiceFlows []Handle
Enrollments []Handle
StepUps []Handle
Ceremonies []Handle
TOTPRecovery []Handle
LogoutIndexes []Handle
Revoked bool
Tombstone bool
}
SessionAnchor is the bounded server-side identity and active-flow index for one browser session.
type SessionRepository ¶
type SessionRepository interface {
Repository[SessionAnchor]
}
SessionRepository persists the browser session anchor independently from protocol flows.
type StepUpRecord ¶
type StepUpRecord struct {
Record
Session Handle
Flow Handle
AuthOutcome string
PendingIdentityReference string
PendingIdentity IdentitySummary
PendingBackendAffinity BackendAffinitySummary
SelfServiceOperation string
SelfServiceCredentialID string
SelfServiceDeviceName string
RequestedLevel int
SupportedMethods []string
MethodLevels map[string]int
ProofMethod string
CompletedAt time.Time
FreshUntil time.Time
Scope string
Completed bool
}
StepUpRecord owns one dynamic assurance or self-service proof operation.
type TOTPRecoveryRecord ¶
type TOTPRecoveryRecord struct {
Record
Session Handle
Flow Handle
AccountReference string
IdentityReference string
OperationID string
Kind string
PendingMaterial []byte
RecoveryCodes []string
Generated bool
Saved bool
RetryCount uint8
}
TOTPRecoveryRecord owns short-lived TOTP or recovery-code operation state.
type Transaction ¶
type Transaction interface {
Commit(ctx context.Context, request TransactionRequest) (TransactionReceipt, error)
}
Transaction begins one atomic multi-record mutation.
type TransactionFactory ¶
type TransactionFactory interface {
Begin(ctx context.Context, session Handle) (Transaction, error)
}
TransactionFactory creates transactions bound to one browser session anchor.
type TransactionReceipt ¶
type TransactionReceipt struct {
Revision Revision
}
TransactionReceipt reports the committed anchor revision.
type TransactionRequest ¶
type TransactionRequest struct {
Session *CommitRequest[SessionAnchor]
OIDC []CommitRequest[OIDCFlow]
SAML []CommitRequest[SAMLFlow]
SelfService []CommitRequest[SelfServiceFlow]
Enrollment []CommitRequest[EnrollmentRecord]
StepUp []CommitRequest[StepUpRecord]
Ceremony []CommitRequest[CeremonyRecord]
TOTPRecovery []CommitRequest[TOTPRecoveryRecord]
Logout []CommitRequest[LogoutIndex]
}
TransactionRequest groups typed writes and deletions that must become visible together.