oauth2
Generated by the pinned ess generate --kind docs from ess. Structural validation establishes consistency; behaviour, storage and cross-record predicates remain implementation obligations.
Provider-neutral OAuth 2.0 authorization servers a profile declares, and the access tokens the host issues to a local caller from a stored grant.
connectors.oauth2 is one of connectors's bounded contexts. Back to the index.
Types
ClientKind
connectors.oauth2.ClientKind is one of public and confidential.
Delivery
connectors.oauth2.Delivery is one of metadata_only, revealed, library and consumer_launch.
GrantType
connectors.oauth2.GrantType is one of authorization_code and device_code.
IssueDecision
connectors.oauth2.IssueDecision is one of current, refreshed, not_ready, reauthorization_required, refresh_uncertain, rate_limited and unavailable.
Parameter
connectors.oauth2.Parameter is a record of two fields:
name—Stringvalue—String
RedirectKind
connectors.oauth2.RedirectKind is one of loopback_any_port, loopback_fixed_port and pasted_code.
RequestEncoding
connectors.oauth2.RequestEncoding is one of form and json.
Rotation
connectors.oauth2.Rotation is one of non_rotating and rotating.
ServerDeclaration
connectors.oauth2.ServerDeclaration is a record of 18 fields:
authorize_url—Optional<String>, which may be absenttoken_url—Stringdevice_authorization_url—Optional<String>, which may be absentclient_id—Optional<String>, which may be absentclient_kind—connectors.oauth2.ClientKindrequest_encoding—connectors.oauth2.RequestEncodingrefresh_encoding—connectors.oauth2.RequestEncodingredirect_kind—connectors.oauth2.RedirectKindredirect_uri—Optional<String>, which may be absentauthorize_parameters—List<connectors.oauth2.Parameter>requested_scopes—List<String>required_scopes—List<String>rotation—connectors.oauth2.Rotationrefresh_lead_seconds—Integergrant_types—List<connectors.oauth2.GrantType>sources—List<String>state_in_exchange—Booleanscope_in_refresh—Boolean
Entities
An entity is what this context is about: something with an identity that outlives any one request, a shape, and a lifecycle. The lifecycle is exhaustive — a move that is not drawn below is a move this specification does not permit, and that is the only way it says so. Every move is labelled with the command that takes it, because a move nothing can trigger is refused rather than drawn.
AccessTokenIssue
connectors.oauth2.AccessTokenIssue.
An instance is identified by issue_ref, a String. The name is part of the model and not a convention: a view projects the identity under that name, so a projection inventing its own would disagree with the view.
It holds:
connection_ref—Stringgeneration_id—connectors.credentials.CredentialGenerationIdrefresh_attempt_id—Optional<connectors.refresh.RefreshAttemptId>, which may be absentexpires_at—Timestampscopes—List<String>delivery—connectors.oauth2.Delivery
It references at most one connectors.auth_bindings.Connection, as connection, carried by AccessTokenIssue.connection_ref. It references at most one connectors.credentials.CredentialGeneration, as generation, carried by AccessTokenIssue.generation_id. It references at most one connectors.refresh.RefreshAttempt, as refresh_attempt, carried by AccessTokenIssue.refresh_attempt_id.
No invariant is declared, so nothing here constrains an instance at rest.
Its state is a connectors.oauth2.AccessTokenIssue.State, one of Issued. That enum is synthesised from the lifecycle rather than declared beside it, so the states a view's filter compares and the states drawn below cannot disagree.
An instance is created in Issued. Issued is terminal, so an instance may rest there forever. That is declared rather than inferred from having no way out: an entity that cannot leave a state is either finished or stuck, and only its author knows which.
It declares no moves, so nothing changes its state once it exists.
It has one state, so there is no move to permit or to forbid.
One view projects it: AccessTokenIssues.
AuthorizationServer
connectors.oauth2.AuthorizationServer.
An instance is identified by server_ref, a String. The name is part of the model and not a convention: a view projects the identity under that name, so a projection inventing its own would disagree with the view.
It holds:
profile_record_ref—Stringdeclaration—connectors.oauth2.ServerDeclaration
It references at most one connectors.auth_bindings.AuthProfile, as auth_profile, carried by AuthorizationServer.profile_record_ref.
No invariant is declared, so nothing here constrains an instance at rest.
Its state is a connectors.oauth2.AuthorizationServer.State, one of Declared. That enum is synthesised from the lifecycle rather than declared beside it, so the states a view's filter compares and the states drawn below cannot disagree.
An instance is created in Declared. Declared is terminal, so an instance may rest there forever. That is declared rather than inferred from having no way out: an entity that cannot leave a state is either finished or stuck, and only its author knows which.
It declares no moves, so nothing changes its state once it exists.
It has one state, so there is no move to permit or to forbid.
One view projects it: AuthorizationServers.
Views
A view is what the outside world is promised it can observe. Each one says which instances it contains and how soon it reflects a command that has already returned, because "you can read this" without "how soon" is the promise every flaky suite is built on.
AccessTokenIssues
connectors.oauth2.AccessTokenIssues.
It reads AccessTokenIssue.
It contains every instance of that entity: no filter narrows it, which is a decision somebody made and not a line somebody omitted.
It exposes:
issue_ref—Stringconnection_ref—Stringgeneration_id—connectors.credentials.CredentialGenerationIdrefresh_attempt_id—Optional<connectors.refresh.RefreshAttemptId>, which may be absentexpires_at—Timestampdelivery—connectors.oauth2.Deliverystate—connectors.oauth2.AccessTokenIssue.State
It declares no order, so the rows come back in whatever order the implementation has, and two reads may disagree.
Read-your-writes: it is current the moment the command that changed it returns. A caller that has just created an invoice and cannot see it in here has been told a lie about what it did.
A generated scenario asserts it once, immediately after the command: a view promising this and not keeping the promise has to fail the suite rather than be retried until it passes.
AuthorizationServers
connectors.oauth2.AuthorizationServers.
It reads AuthorizationServer.
It contains every instance of that entity: no filter narrows it, which is a decision somebody made and not a line somebody omitted.
It exposes:
server_ref—Stringprofile_record_ref—Stringstate—connectors.oauth2.AuthorizationServer.State
It declares no order, so the rows come back in whatever order the implementation has, and two reads may disagree.
Read-your-writes: it is current the moment the command that changed it returns. A caller that has just created an invoice and cannot see it in here has been told a lie about what it did.
A generated scenario asserts it once, immediately after the command: a view promising this and not keeping the promise has to fail the suite rather than be retried until it passes.
Commands
DeclareAuthorizationServer
connectors.oauth2.DeclareAuthorizationServer.
It takes:
profile_record_ref—Stringdeclaration—connectors.oauth2.ServerDeclaration
It has one outcome.
declared — The default branch, taken when no other outcome's condition matched. It creates a connectors.oauth2.AuthorizationServer, which starts in Declared. The new instance's identity is published as server_ref on connectors.oauth2.AuthorizationServerDeclared. It emits connectors.oauth2.AuthorizationServerDeclared. It sets profile_record_ref from input.profile_record_ref and declaration from input.declaration. A test reaches it by constructing an input that satisfies no other outcome's condition.
IssueAccessToken
connectors.oauth2.IssueAccessToken.
It takes:
decision—connectors.oauth2.IssueDecisionconnection_ref—Stringgeneration_id—connectors.credentials.CredentialGenerationIdrefresh_attempt_id—Optional<connectors.refresh.RefreshAttemptId>, which may be absentexpires_at—Timestampscopes—List<String>delivery—connectors.oauth2.Delivery
It has seven outcomes.
issued-current — Taken when (decision == current and not (defined(refresh_attempt_id))) holds of the input. It creates a connectors.oauth2.AccessTokenIssue, which starts in Issued. The new instance's identity is published as issue_ref on connectors.oauth2.AccessTokenIssued. It emits connectors.oauth2.AccessTokenIssued. It sets connection_ref from input.connection_ref, generation_id from input.generation_id, refresh_attempt_id cleared, expires_at from input.expires_at, scopes from input.scopes and delivery from input.delivery. A test reaches it by constructing an input that satisfies that condition.
issued-refreshed — Taken when (decision == refreshed and defined(refresh_attempt_id)) holds of the input. It creates a connectors.oauth2.AccessTokenIssue, which starts in Issued. The new instance's identity is published as issue_ref on connectors.oauth2.AccessTokenIssued. It emits connectors.oauth2.AccessTokenIssued. It sets connection_ref from input.connection_ref, generation_id from input.generation_id, refresh_attempt_id from input.refresh_attempt_id, expires_at from input.expires_at, scopes from input.scopes and delivery from input.delivery. A test reaches it by constructing an input that satisfies that condition.
not-ready — Taken when decision == not_ready holds of the input. No entity in this specification changes. It reports connectors.oauth2.ConnectionNotReady, carrying connection_ref. It emits nothing. A test reaches it by constructing an input that satisfies that condition.
reauthorization-required — Taken when decision == reauthorization_required holds of the input. No entity in this specification changes. It reports connectors.oauth2.ReauthorizationRequired, carrying connection_ref. It emits nothing. A test reaches it by constructing an input that satisfies that condition.
refresh-uncertain — Taken when decision == refresh_uncertain holds of the input. No entity in this specification changes. It reports connectors.oauth2.RefreshUncertain, carrying connection_ref. It emits nothing. A test reaches it by constructing an input that satisfies that condition.
rate-limited — Taken when decision == rate_limited holds of the input. No entity in this specification changes. It reports connectors.oauth2.RateLimited, carrying connection_ref. It emits nothing. A test reaches it by constructing an input that satisfies that condition.
unavailable — The default branch, taken when no other outcome's condition matched. No entity in this specification changes. It reports connectors.oauth2.Unavailable. It emits nothing. A test reaches it by constructing an input that satisfies no other outcome's condition.
Events
AccessTokenIssued
connectors.oauth2.AccessTokenIssued.
It carries:
issue_ref—Stringrefreshed—Boolean
Emitted by connectors.oauth2.IssueAccessToken on its issued-current and issued-refreshed outcomes.
Nothing in this system reacts to it.
AuthorizationServerDeclared
connectors.oauth2.AuthorizationServerDeclared.
It carries:
server_ref—String
Emitted by connectors.oauth2.DeclareAuthorizationServer on its declared outcome.
Nothing in this system reacts to it.
Errors
ConnectionNotReady
It carries:
connection_ref—String
Reported by connectors.oauth2.IssueAccessToken on its not-ready outcome.
RateLimited
It carries:
connection_ref—String
Reported by connectors.oauth2.IssueAccessToken on its rate-limited outcome.
ReauthorizationRequired
It carries:
connection_ref—String
Reported by connectors.oauth2.IssueAccessToken on its reauthorization-required outcome.
RefreshUncertain
It carries:
connection_ref—String
Reported by connectors.oauth2.IssueAccessToken on its refresh-uncertain outcome.
Unavailable
It carries nothing beyond its name, so a caller can tell what went wrong and not which value caused it.
Reported by connectors.oauth2.IssueAccessToken on its unavailable outcome.
Actors
An actor is who may ask this context for something. Every grant below points at a command this specification declares — a grant is a resolved reference, so "may invoke" something nobody wrote is not a permission this model can express, and an authorisation that authorises nothing cannot ship quietly.
LocalHost
connectors.oauth2.LocalHost.
It may invoke DeclareAuthorizationServer and IssueAccessToken.
Generated from connectors v1 · model digest e1e1672d0af4753cb8f2da6c0b22a7f6ae8ce9f7abc168f86169babdf1325787 · contract digest slice-sha256/2:1440fa22f92c9789a5206d2b0499a45b7a676acf4ea68320bdc1921731a4ed29. Do not edit this file; change the specification and regenerate it with ess generate.