Raxx · internal docs

internal · gated

handoff-spec.json Schema

Ref: SC-HANDOFF-SESSIONCTX-01 (#3748) — ADR-0131 §4.5

Used by provision_handoff_full.py (provisioning) and build_handoff_session_context.py (session_context injection).


Required fields

Field Type Description
task_slug string Canonical task identifier. Format: <short-desc>-<YYYYMMDD>. Used in vault path, PAT name, and audit trail. Must match the GitHub issue slug.
surfaces string[] Credential surfaces to provision. Valid values: infisical, github, stripe, cloudflare, aws, heroku, apple_iap.
operator_approval string Free-text approval record. Convention: "Kristerpher YYYY-MM-DD". Required by ADR-0131 §6.2.
linked_card integer GitHub issue number this handoff is performing work for.

Optional fields

Field Type Default Description
expected_runtime string (ISO 8601 duration) "PT1H" Expected task duration. Tasks exceeding 1h are enrolled in Velvet auto-revoke (SC-HANDOFF-VELVET-01).
ttl_expires_at string (ISO 8601 UTC) 24h from provisioning Hard TTL. The gate blocks dispatch after this timestamp. Format: "2026-06-22T04:00:00Z".
repo string "TradeMasterAPI" GitHub repository name (no owner prefix).
owner string "raxx-app" GitHub repository owner.
ttl_hours integer 24 PAT TTL in hours. Maximum 24 (ADR-0131 H3).
mcp_tools string[] baseline set Explicit MCP tool allowlist for the agent session. See tool catalogue below.
aws_inline_policy object none IAM inline policy JSON for STS AssumeRole narrowing.

MCP tool allowlist

The mcp_tools field lists the EXACT set of MCP tools the agent may call. Tools NOT on the list are stripped from the session and recorded in mcp_tools_excluded for audit clarity.

build_handoff_session_context.py enforces:

  1. BASELINE_ALLOWED_TOOLS (always included, cannot be removed by spec): - github_pr_create, github_pr_comment, github_pr_update, github_issue_comment - infisical_get_secret - git_read, git_status, git_diff, git_log

  2. ALWAYS_EXCLUDED_TOOLS (hard never-allow, stripped even if in spec): - stripe_charge, stripe_refund, stripe_customer_create - apple_iap_purchase, apple_iap_refund - heroku_scale_dynos - filesystem_write_outside_worktree - infisical_set_secret, infisical_delete_secret - email_send - aws_s3_write, aws_invoke_lambda - cf_dns_update

  3. Spec-addable tools (must be listed in mcp_tools to be available): - git_commit, git_push, git_fetch — source control write ops - filesystem_read, filesystem_write — in-worktree filesystem - bash_exec_in_worktree — bounded shell access - github_pr_merge, github_issue_create, github_issue_close - heroku_config_get — read-only Heroku config - aws_s3_read, email_read

Example: PR-writing agent (issues #3629, #3206)

{
  "task_slug": "iap-notif-handler-20260621",
  "surfaces": ["infisical", "github"],
  "expected_runtime": "PT4H",
  "ttl_expires_at": "2026-06-22T04:00:00Z",
  "operator_approval": "Kristerpher 2026-06-21",
  "linked_card": 3629,
  "repo": "TradeMasterAPI",
  "owner": "raxx-app",
  "ttl_hours": 4,
  "mcp_tools": [
    "github_pr_create",
    "github_pr_comment",
    "infisical_get_secret",
    "git_commit",
    "git_push",
    "filesystem_read",
    "filesystem_write",
    "bash_exec_in_worktree"
  ]
}

The resulting session_context env will contain: - INFISICAL_CLIENT_ID — per-task machine identity (not operator ID) - INFISICAL_CLIENT_SECRET — per-task machine secret - INFISICAL_SECRET_PATH/MooseQuest/handoffs/iap-notif-handler-20260621/ - GH_TOKEN — scoped fine-grained PAT (contents:write, pull_requests:write, issues:write only) - HANDOFF_TASK_SLUGiap-notif-handler-20260621 - HANDOFF_EXPIRES_AT2026-06-22T04:00:00Z

Gate + injection flow

operator runs:
  python3 scripts/agents/provision_handoff_full.py --spec handoff-spec.json

orchestrator runs (Step 0 of every dispatch):
  python3 scripts/agents/build_handoff_session_context.py \
      --task-slug <slug> \
      --spec handoff-spec.json

      # Internally calls check_handoff_gate.run_gate() — blocks if gate fails.
      # Reads scoped creds from vault.
      # Emits session_context JSON to stdout.
      # Orchestrator injects into CCR job_config.ccr.session_context.

Revocation

python3 scripts/agents/provision_handoff_full.py --task-slug <slug> --revoke

Removes the vault path and revokes the GitHub PAT. Stripe / Cloudflare / AWS tokens also need per-surface external revocation (see runbook: docs/ops/runbooks/handoff-provisioning.md).