Skip to content

Permission grant delivery depends on an undocumented, fragile actor invariant; 300s timeout is hardcoded #97

@nficano

Description

@nficano

Category: bug Severity: major
Location: Sources/ARCP/Runtime/JobManager.swift:426-458, Sources/ARCP/Runtime/ARCPRuntime.swift:262-288
Spec: ARCP v1.1 §15.4

What

The handler runs in a child Task (runJob), so requestPermission's await permissionRegistry.awaitResponse does not directly block the JobManager actor. But the response that unblocks it (permission.grant/permission.deny) arrives through the same dispatchLoophandlejobManager.handlePermissionGrant. The dispatch loop processes envelopes one at a time and awaits each handle call. The current code avoids deadlock only because runJob is a separate Task; if any handler does synchronous (non-Task) permission requests directly on the JobManager actor (e.g., a future refactor or the inline credential issuance path), the actor is occupied and the grant cannot be delivered. This invariant is undocumented and untested. The 300s hardcoded timeout (.seconds(300)) also ignores the caller-supplied leaseSeconds/any client deadline.

Evidence

let outcome = try await permissionRegistry.awaitResponse(id: id, deadline: timeout)

called with timeout: .seconds(300) hardcoded in ConcreteJobContext.requestPermission. Resolution depends entirely on the serial dispatchLoop delivering permission.grant.

Proposed fix

  1. Document (and add a regression test for) the invariant that handler execution must run off the JobManager actor's serial executor so permission responses can be delivered.
  2. Make the permission timeout configurable rather than a hardcoded 300s.

Acceptance criteria

  • A test demonstrates a handler can request a permission and receive a grant on the same session without deadlock.
  • Permission timeout is configurable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    audit/bugAudit: bug / inefficiency / oversized filesev/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