Abstract endpoint-specific mutation rejections

This commit is contained in:
ms2k 2026-07-13 18:36:32 +09:00
commit 78be27871c
3 changed files with 11 additions and 7 deletions

View file

@ -12,7 +12,7 @@ CONSTANTS
NoRecord = NoRecord NoRecord = NoRecord
NoObservation = NoObservation NoObservation = NoObservation
Accepted = Accepted Accepted = Accepted
PreconditionFailed = PreconditionFailed Rejected = Rejected
FirstObservation = FirstObservation FirstObservation = FirstObservation
ReplayObservation = ReplayObservation ReplayObservation = ReplayObservation
ConflictObservation = ConflictObservation ConflictObservation = ConflictObservation

View file

@ -7,7 +7,7 @@ EXTENDS Naturals, FiniteSets
CONSTANTS CONSTANTS
OperationScopes, EligibilityClaims, OperationIds, MutationKinds, OperationScopes, EligibilityClaims, OperationIds, MutationKinds,
Fingerprints, NoEligibility, NoRecord, NoObservation, Fingerprints, NoEligibility, NoRecord, NoObservation,
Accepted, PreconditionFailed, Accepted, Rejected,
FirstObservation, ReplayObservation, ConflictObservation FirstObservation, ReplayObservation, ConflictObservation
ASSUME ASSUME
@ -26,8 +26,10 @@ Requests ==
kind : MutationKinds, kind : MutationKinds,
fingerprint : Fingerprints] fingerprint : Fingerprints]
\* Rejected abstracts endpoint-specific idempotency_conflict and
\* precondition_failed responses exercised by the executable contract.
Responses == Responses ==
[status : {Accepted, PreconditionFailed}, [status : {Accepted, Rejected},
revision : 0..Cardinality(Identities)] revision : 0..Cardinality(Identities)]
Records == [request : Requests, response : Responses] Records == [request : Requests, response : Responses]
@ -60,7 +62,7 @@ FirstRequest(request) ==
accepted == Eligible(request) accepted == Eligible(request)
nextRevision == IF accepted THEN revision + 1 ELSE revision nextRevision == IF accepted THEN revision + 1 ELSE revision
response == response ==
[status |-> IF accepted THEN Accepted ELSE PreconditionFailed, [status |-> IF accepted THEN Accepted ELSE Rejected,
revision |-> nextRevision] revision |-> nextRevision]
record == [request |-> request, response |-> response] record == [request |-> request, response |-> response]
IN /\ records[identity] = NoRecord IN /\ records[identity] = NoRecord
@ -89,7 +91,7 @@ ConflictRequest(request) ==
LET identity == Identity(request) LET identity == Identity(request)
record == records[identity] record == records[identity]
response == response ==
[status |-> PreconditionFailed, revision |-> revision] [status |-> Rejected, revision |-> revision]
IN /\ record # NoRecord IN /\ record # NoRecord
/\ record.request # request /\ record.request # request
/\ observation' = /\ observation' =
@ -144,7 +146,7 @@ ObservationConsistent ==
/\ record.response = observation.response /\ record.response = observation.response
[] observation.disposition = ConflictObservation -> [] observation.disposition = ConflictObservation ->
/\ record.request # observation.request /\ record.request # observation.request
/\ observation.response.status = PreconditionFailed /\ observation.response.status = Rejected
RecordsAppendOnlyAction == RecordsAppendOnlyAction ==
\A identity \in Identities : \A identity \in Identities :

View file

@ -31,7 +31,9 @@ fresh operation is evaluated against current eligibility.
[`RemoraApiMutation`](../../protocol/RemoraApiMutation.tla) models this durable [`RemoraApiMutation`](../../protocol/RemoraApiMutation.tla) models this durable
operation ledger around an abstract successful `JobProtocol` effect. It does operation ledger around an abstract successful `JobProtocol` effect. It does
not redefine job phases or attempt-authority transitions. not redefine job phases or attempt-authority transitions. Its `Rejected`
response abstracts the endpoint-specific `idempotency_conflict` and
`precondition_failed` codes enforced by the executable contract.
## Authorization and errors ## Authorization and errors