Skip to content

Repository files navigation

Agent Mandate Verification Gate

Use this GitHub Action to verify a proposed AI-agent action against an existing signed Agent Mandate before a workflow continues. It is deliberately fail-closed: anything other than a complete, cardinality-matched set of allow receipts fails the step.

Quick start

Store the caller's Agent Mandate API key as AGENT_MANDATE_API_KEY and the complete signed mandate envelope as AGENT_MANDATE_SIGNED_JSON. Then add a workflow step like this:

- name: Verify proposed agent actions
  uses: API-Disk-Integrations/agent-mandate-action@v1
  with:
    actions-file: mandate/proposed-actions.json
  env:
    AGENT_MANDATE_API_KEY: ${{ secrets.AGENT_MANDATE_API_KEY }}
    AGENT_MANDATE_SIGNED_JSON: ${{ secrets.AGENT_MANDATE_SIGNED_JSON }}

For the strongest supply-chain guarantee, replace v1 with the immutable 40-character commit SHA from the release you reviewed.

Exact operation and boundary

The Action sends one validated request to POST https://agentmandate-api.com/v1/verify. A caller supplies an existing signed mandate plus one proposed action or an ordered batch of at most 500. The Action preserves each exact server decision: allow, deny, or requires_approval.

The CI step succeeds only when response cardinality exactly matches the request and every receipt is allow. Any denial, approval requirement, malformed or incomplete response, timeout, network failure, API error, or unexpected receipt count fails closed. The Action does not issue or revoke a mandate, approve an action, execute an action, move money, change data, call billing, write to GitHub, or retry a request.

The accepted endpoint contract makes agent optional syntactically while explicitly instructing callers to supply it to prevent replay by a different agent. This security-focused Action profile therefore requires agent on every proposed action. It also refuses wildcard proposals because the contract defines wildcards as grants, not concrete actions. These are local client restrictions; they do not claim different API semantics.

Inputs and secrets

Map two user-controlled GitHub secrets into environment variables:

  • AGENT_MANDATE_API_KEY: the caller's Agent Mandate API key.
  • AGENT_MANDATE_SIGNED_JSON: the complete JSON object returned by POST /v1/mandates, including its signature.

Neither value is declared as an Action input. Attempts to pass api-key or mandate-json as plain inputs fail closed. The API key, detached signature, and any supplied approvalToken are registered with the runner's masking protocol before the request. The implementation never logs the signed mandate, API key, approval token, proposal, raw response, server message, or receipt identity fields.

The candidate validates the documented {mandate, signature} envelope and v1:<hex> detached-signature format locally. It never attempts local cryptographic verification; the accepted /v1/verify service performs that account-bound check.

Supply exactly one proposal source:

  • action-json: one documented action object; or
  • actions-file: a repository-relative regular JSON file containing an ordered array of 1–500 documented action objects.

An action requires agent and action; it may contain resource, amountMinor, currency, priorSpendMinor, priorCount, approvalToken, and at. amountMinor is a nonnegative integer and requires currency. Explicit at values make the evaluation instant reproducible. Unknown action fields, final symlinks, path escapes, invalid JSON, oversized inputs, and ambiguous sources are rejected before the API request.

The signed mandate is limited to 256 KiB, inline action JSON to 64 KiB, batch files and responses to 1 MiB. The Action makes exactly one request with a 30-second timeout and no retry. One verification request can still consume a metered unit per proposed action under the product contract.

Recommended workflow shape

This example excludes pull requests and pull_request_target so secrets are not exposed to untrusted code. Replace each placeholder with the immutable 40-character commit SHA you reviewed.

name: Agent Mandate verification

on:
  workflow_dispatch:
  push:
    branches: [main]

permissions:
  contents: read

jobs:
  authorize:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<REVIEWED_FULL_40_CHARACTER_COMMIT_SHA>
        with:
          persist-credentials: false
      - name: Verify proposed actions only
        uses: API-Disk-Integrations/agent-mandate-verify@<REVIEWED_FULL_40_CHARACTER_COMMIT_SHA>
        with:
          actions-file: mandate/proposed-actions.json
        env:
          AGENT_MANDATE_API_KEY: ${{ secrets.AGENT_MANDATE_API_KEY }}
          AGENT_MANDATE_SIGNED_JSON: ${{ secrets.AGENT_MANDATE_SIGNED_JSON }}

Never expose these secrets to forked or otherwise untrusted pull-request code. Do not add pull_request_target, a plain secret input, a writable GitHub token, an unpinned third-party Action, or a later execution step that ignores this step's failure.

Outputs and report

The Action sets all-allowed, receipt-count, and report-path. It writes a new file at .agent-mandate/verification-report.json; a pre-existing report directory is rejected to prevent symlink or hard-link overwrite attacks.

The report contains only per-receipt order, exact decision, violation count, validated SHA-256 evaluation digest when present, aggregate decision counts, and the exact receipt count. It excludes mandate ID, principal, agent, proposed action, resource, amount, approval token, matched grant, violation codes/details, raw mandate, API key, and raw response. The step summary contains only aggregate counts and the relative report path.

Local verification

npm ci --offline --ignore-scripts --no-audit --no-fund
npm run check
npm audit --offline --omit=dev
npm pack --dry-run --json

All tests use deterministic local fetch mocks and sentinel noncredentials. The bundle has no runtime install, does not use the GitHub API, and makes no production request during build or test.

Versioning and support

  • Immutable releases use semantic tags such as v1.0.0.
  • The v1 major alias may advance only to a reviewed compatible release.
  • Pin the immutable commit SHA when your workflow requires strict provenance.
  • Open a GitHub issue for defects. Do not include API keys, signed mandates, approval tokens, request bodies, receipts, or customer data.

The Action calls the production Agent Mandate verification API, but a listing, install, download, or test run is not evidence of customer activation or revenue.

About

Fail-closed verification gate for proposed AI-agent actions

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages