Skip to content

Permanent credential revocation failure not logged or surfaced (§9.8.2, §14) #87

@nficano

Description

@nficano

Category: spec-conformance Severity: major
Location: src/Arcp.Runtime/Internal/CredentialRegistry.fs:31-57
Spec: ARCP v1.1 §9.8.2

What

Spec §9.8.2: 'Revocation is best-effort; the runtime SHOULD retry on transient failure and MUST log permanent failures.' §14: runtimes must 'surface unrevocable credentials to operators.' When the retry loop exhausts with revoked=false, the credential id stays in perJob/store with no log, no telemetry, no operator-visible signal.

Evidence

let revokeWithRetryAsync ... =
    task {
        let mutable revoked = false
        let mutable attempt = 0
        while not revoked && attempt < retryDelays.Length do
            let! doneOrPermanent = provisioner.RevokeAsync(credentialId, ct)
            if doneOrPermanent then revoked <- true
            else
                do! Task.Delay(retryDelays.[attempt], ct)
                attempt <- attempt + 1
        if revoked then
            ...
    }

Proposed fix

On loop exit with revoked=false: emit a structured log/trace (ILogger or built-in Console fallback) including jobId and credentialId, and persist a revocation_failed marker in the store so operators can list dangling credentials. Optionally also push to an IRevocationFailureSink.

Acceptance criteria

  • After the third retry returns transient-fail, a warning/error log line is emitted with the credential id and job id; the store exposes the failure to an operator query.

Metadata

Metadata

Assignees

No one assigned

    Labels

    audit/spec-conformanceAudit finding — ARCP v1.1 spec conformancesev/majorSeverity — major

    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