Skip to content

Idempotency always rejects key reuse instead of returning original job.accepted (§7.2) #135

@nficano

Description

@nficano

Category: spec-conformance Severity: blocker
Location: server/session.go:545-560
Spec: ARCP v1.1 §7.2

What

Spec §7.2: 'the runtime MUST return the same job.accepted payload for any subsequent submission with the same key and identical parameters. A reused key with conflicting parameters returns DUPLICATE_KEY.' The Go SDK returns DUPLICATE_KEY for every key reuse without comparing parameters and without re-emitting the original job.accepted, breaking client retry semantics.

Evidence

	if req.IdempotencyKey != "" {
		entry, fresh, err := s.srv.idStore.PutIfAbsent(ctx, idstore.Entry{
			Principal: s.principal,
			Key:       req.IdempotencyKey,
			JobID:     job.id,
			CreatedAt: s.srv.opts.Clock.Now(),
		})
		if err != nil {
			s.srv.unregisterJob(job.id)
			return s.sendError(arcp.Code(err), "idempotency store error: "+err.Error())
		}
		if !fresh {
			s.srv.unregisterJob(job.id)
			return s.sendError(arcp.CodeDuplicateKey, "idempotency key already used for job "+entry.JobID)
		}
	}

Proposed fix

Persist the original JobSubmit payload (or its canonical hash + job.accepted snapshot) in the idstore; on PutIfAbsent miss, compare new request to stored params — if equal, re-emit the cached job.accepted; if different, return DUPLICATE_KEY.

Acceptance criteria

  • Re-submitting an unchanged JobSubmit with the same idempotency_key yields the same job.accepted (same job_id, lease, accepted_at); submitting with the same key but altered input/lease yields DUPLICATE_KEY.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions