Skip to content

Design Telegram human-in-the-loop capability approvals #1

Description

@ak5

Goal

Add an optional human-in-the-loop approval flow in which an external Telegram
bot presents a precise requested capability and an authorized person may deny
it or approve it once or through a bounded reusable rule.

Example prompt:

Is workload release-agent in workspace ws-123 allowed to run
gh issue close 456 against github.com/acme/widgets?

Actions:

  • Deny
  • Allow once
  • Allow for this session
  • Always allow this exact operation
  • Always allow this bounded operation class (for example, GitHub Issues
    operations for one tenant/persona/repository)

Architectural constraint

Telegram is an approval user interface, not part of Charon's credential data
plane and not a source of credential, endpoint, provider, item, hostname,
method, path, or secret-reference selection.

An external approval broker should:

  1. receive a normalized capability request from the integrating control plane;
  2. render only redacted identity and concrete operation information;
  3. authenticate an allowlisted Telegram chat/user;
  4. record the decision and any bounded reusable rule;
  5. return a signed approval assertion to the workload-identity issuer; and
  6. let the issuer mint Charon's existing short-lived, single-use manifest.

Charon should continue verifying manifests offline. It must not call Telegram or
wait on a chat interaction while holding an HTTP request or resolved secret.

Required decisions

  • Define the normalized approval-request schema and canonical request digest.
  • Decide whether approval assertions need their own key and schema or remain an
    issuer-internal contract.
  • Define the exact predicates available to reusable rules:
    • tenant, persona, workload, and optionally workspace;
    • service and exact account/organization/repository resource;
    • named capability and operation class;
    • maximum duration, use count, and manifest TTL;
    • environment or risk tier.
  • Define an approval session as an issuer-authenticated tenant, persona,
    workspace, and active lease tuple—not a Telegram chat session or a
    workload-supplied identifier.
  • Bound session approval by the earliest of lease termination, workspace
    disposal, explicit revocation, inactivity timeout, and configured maximum
    duration.
  • Define which operations can never receive reusable approval.
  • Define rule creation, listing, expiry, revocation, and emergency disable.
  • Define behavior when Telegram or the approval broker is unavailable
    (fail closed).
  • Decide how Telegram account recovery, bot-token rotation, and chat migration
    affect authorization.

“Always” must never mean an unbounded natural-language match. A label such as
“anything relating to GitHub Issues” must compile to inspectable structured
predicates, such as one persona, one repository, a fixed set of issue
operations, and a bounded expiry.

Security requirements

  • Bind each prompt and callback to a random, single-use, expiring approval ID
    and a digest of the complete normalized request.
  • Reject stale, replayed, edited, duplicated, or mismatched callbacks.
  • Use Telegram numeric user and chat IDs from an operator allowlist; do not
    authorize by username or display name.
  • Ensure only the current pending message can mutate its decision; edit it to a
    terminal redacted result after use.
  • Keep bot tokens, approval-signing keys, manifests, nonces, credentials,
    provider references, and private resource data out of messages and logs.
  • Make deny and timeout the default.
  • Never let session approval survive lease replacement, workspace resume into a
    new lease, persona reassignment, or approval-broker restart without durable,
    revocable state.
  • Mint a fresh short-lived, single-use Charon manifest for every operation
    covered by a session approval; the approval itself is never a reusable
    Charon bearer token.
  • Require stronger confirmation for creating or widening reusable rules.
  • Prevent a workload from selecting or weakening the reusable-rule scope.
  • Preserve Charon's independent concrete destination/method/path enforcement;
    human approval cannot override local deny-by-default policy.
  • Emit correlated, redacted audit records for request, delivery, decision,
    rule match, issuer result, revocation, and timeout.
  • Rate-limit prompts and prevent approval-notification flooding.
  • Document Telegram as an external availability and account-takeover risk, not
    as a secret store.

Suggested contracts

  • approval-request.schema.json
  • approval-decision.schema.json
  • approval-rule.schema.json
  • Optional OpenAPI for the approval broker's authenticated control-plane API
  • Telegram adapter behind an ApprovalChannel interface so other channels can
    be added without changing decision semantics

The channel adapter should only deliver a presentation model and return an
opaque decision callback. Policy normalization and authorization belong in the
approval broker, not Telegram-specific code.

Acceptance criteria

  • ADR records trust boundaries, rule semantics, failure behavior, and
    rejected alternatives.
  • Telegram bot supports deny, allow-once, session-duration approval, exact
    reusable approval, and bounded operation-class approval.
  • Allow-once cannot be replayed and expires before or with the resulting
    manifest.
  • Session approval is bound to one authenticated tenant/persona/workspace/
    lease tuple and ends on lease termination, disposal, revocation,
    inactivity timeout, or maximum duration.
  • Suspend/resume or lease replacement does not carry session approval into
    the new lease.
  • Reusable rules are structured, inspectable, expiring, and revocable.
  • Cross-tenant, cross-persona, cross-workspace, cross-repository, widened
    operation, edited callback, duplicate callback, and expired callback
    attempts fail.
  • Telegram outage, bot removal, unknown user/chat, and approval-broker
    outage fail closed without interrupting already authorized unrelated
    realms.
  • Charon has no Telegram dependency and makes no online approval lookup.
  • No prompt, callback, API response, log, trace, or fixture leaks
    credentials, manifests, nonces, signing keys, provider references, or
    private keys.
  • Threat model, integration-boundary documentation, and operator runbook
    are updated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    designArchitecture and design workpriority:2Normal prioritysecuritySecurity-sensitive work

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions