{
  "schema_version": "1.3.0",
  "slug": "what-happens-when-an-instance-mints-a-delegated-capability-token-whose-scope-set-is-empty-after-per-tool-consent-negotiation",
  "title": "What happens when an instance mints a delegated capability token whose scope set is empty after per-tool consent negotiation",
  "date_of_record": "2026 November 11",
  "scope": "Applies to AAIF delegated capability tokens (DCTs) issued by an agent instance on behalf of a user principal, where per-tool consent is negotiated at issuance time and the token's `scope` claim is a set of tool-scoped capabilities. Does not apply to root principal tokens, service-account tokens, or tokens whose scope is a wildcard/`*` grant, which bypass the negotiation path entirely.",
  "projections": {
    "unified_markdown_uri": "https://corpusfetch.com/c/what-happens-when-an-instance-mints-a-delegated-capability-token-whose-scope-set-is-empty-after-per-tool-consent-negotiation.md",
    "method_python_slice_uri": "https://corpusfetch.com/c/what-happens-when-an-instance-mints-a-delegated-capability-token-whose-scope-set-is-empty-after-per-tool-consent-negotiation.py",
    "remnant_warrant_slice_uri": "https://corpusfetch.com/c/what-happens-when-an-instance-mints-a-delegated-capability-token-whose-scope-set-is-empty-after-per-tool-consent-negotiation.warrant.json"
  },
  "token_profile": {
    "full_markdown_tokens": 1645,
    "python_slice_tokens": 457,
    "warrant_slice_tokens": 220
  },
  "remnant_summary": {
    "core_distinction": "The failure is not \"unauthorized access\" and it is not \"token revocation.\" It is the **empty-scope admission**: a delegated token that is structurally valid, correctly signed, unexpired, and bound to the right principal, but whose negotiated scope set collapsed to the empty set because every requested per-tool capability was declined or filtered during conse...",
    "what_was_observed": "In a three-tier agent deployment (orchestrator → tool gateway → resource server), an agent requested consent for four tools: `fs.read`, `fs.write`, `http.fetch`, `shell.exec`. The user granted only `fs.read`. The consent negotiator, implemented as a set intersection over requested ∩ granted, produced `{fs.read}` — correct. A second path, however, was exercised when the user granted *nothing* (explicit \"deny all\" in t...",
    "condition_of_validity": "The empty-scope token is a *valid* AAIF artifact and must be treated as **deny-all with an authenticated subject**, never as anonymous and never as a cache miss. The invariant that holds: > For any DCT `t`, `authorize(t, tool) == ALLOW` iff `tool ∈ t.scope`. When `t.scope == ∅`, `authorize` is `DENY` for every tool, and the principal is still `t.sub` — the r...",
    "decision_boundary": "The operational rule is a three-way branch at the resource server, not a two-way one: - **Token absent / signature invalid / expired** → `401 Unauthenticated`. Route to anonymous handling. Do not consult caches keyed by principal. - **Token valid, `tool ∉ scope` (including `scope == ∅`)** → `403 Forbidden` with `reason=consent_denied`, principal attached to ...",
    "operational_effect": "Teams that hit this boundary without the three-way branch see: audit trails mislabeling consent denials as authn faults; on-call paging on legitimate user \"deny all\" actions; automated revocation sweeps with blast radius across issuance batches; and principal-keyed caches serving responses across scope boundaries. Teams that adopt the three-way branch and th..."
  },
  "matched_failure_symptoms": [
    "DOMAIN:EPISTEMIC_PROVENANCE_AND_FEDERATION_ROUTING"
  ],
  "composition_edges": {
    "primary_domain": "epistemic_provenance_and_federation_routing",
    "upstream_precondition_residuals": [
      "https://corpusfetch.com/c/according-to-what-precedence-hierarchy-must-an-instance-resolve-contradictory-directives-across-system-developer-and-user-tiers.md",
      "https://corpusfetch.com/c/how-should-an-instance-decide-that-a-stored-conclusion-has-gone-stale-without-a-new-observation.md"
    ],
    "downstream_consequence_residuals": [
      "https://corpusfetch.com/c/by-what-checkpoint-and-compaction-boundaries-must-an-instance-externalize-working-state-to-prevent-context-window-drift-and-truncation-amnesia.md",
      "https://corpusfetch.com/c/across-what-additive-schema-and-unknown-field-preservation-boundaries-must-an-instance-evolve-wire-contracts-to-prevent-rolling-deploy-deserialization-crashes.md"
    ],
    "co_occurring_sibling_residuals": [
      "https://corpusfetch.com/c/how-can-an-instance-capture-implicit-user-preferences-without-storing-private-data.md",
      "https://corpusfetch.com/c/how-can-an-instance-compress-long-reasoning-traces-into-binding-conclusions.md"
    ]
  },
  "empirical_verification_warrant": {
    "status": "AST_AND_INVARIANT_VERIFIED",
    "syntax_valid": true,
    "code_sha256": "bdb4cf59d11375c3b723c28e6e3c9caa48fb7abb0cf8e64e830baf7373879c9f",
    "verified_classes": [
      "EmptyScopeMisclassifiedError",
      "DelegatedCapabilityToken",
      "Decision"
    ],
    "verified_functions": [
      "authorize",
      "mint",
      "_audit",
      "handle_request"
    ],
    "verified_functions_count": 4,
    "defensive_guards_count": 2,
    "raised_exceptions": [
      "EmptyScopeMisclassifiedError"
    ],
    "sample_fail_closed_invariants": [],
    "stdlib_dependencies": [
      "dataclasses",
      "typing"
    ],
    "observation_mode": "EMPIRICAL_BOUNDARY_CAPTURE",
    "zero_external_deps": true
  }
}
