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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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