> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sigilcore.com/llms.txt
> Use this file to discover all available pages before exploring further.

# FAQ & Troubleshooting

> Diagnosing policy violations, validation errors, startup failures, and on-chain verification.

## Setup & Deployment

<AccordionGroup>
  <Accordion title="Can I use Sigil without self-hosting?">
    **Yes. The Sigil API is the recommended path for most teams.**

    Register at [sigilcore.com/tools/keys](https://sigilcore.com/tools/keys)
    to receive a Developer tier API key: 1,000 governed actions per month, free.
    The hosted API handles signing infrastructure, key management, and attestation
    issuance. You still define your own policy via
    [Sigil Warrant](https://sigilcore.com/tools/warrant) and retain full control
    over what your agents can and cannot do.

    **Pricing:**

    * **Developer:** Free, 1,000 governed actions/month
    * **Growth:** $49/month, 10,000 governed actions, $0.002 per action above
    * **Enterprise:** Custom, dedicated infrastructure, SLAs, audit support via
      [Sigil Governance](https://sigilgovernance.com)

    Self-hosting `sigil-sign` is available for teams that require it (MIT-licensed),
    but for most deployments the API is faster to set up and lower maintenance.
  </Accordion>

  <Accordion title="My service failed to start. What does 'warranty.md is missing a ## signature block' mean?">
    Starting with the GAP-001 sprint, Sigil Sign requires every warranty.md to
    be cryptographically signed before it will evaluate policy. An unsigned file
    is rejected at startup, including any file you created manually or copied
    from an older version.

    **To fix this:**

    1. Go to [sigilcore.com/tools/warrant](https://sigilcore.com/tools/warrant)
    2. Generate a keypair (or use your existing private key to re-sign)
    3. Define your policy or paste your existing policy content
    4. Download the signed warranty.md
    5. Deploy it to your server at the path `WARRANTY_PATH` points to
    6. Set `SIGIL_OPERATOR_PUBLIC_KEY` in your environment
    7. Restart the service

    The service will not start without both a signed policy file and the
    corresponding public key in the environment.
  </Accordion>

  <Accordion title="My service failed to start. What does 'SIGIL_OPERATOR_PUBLIC_KEY is not set' mean?">
    Sigil Sign needs your Ed25519 public key to verify that the warranty.md on
    disk was signed by you. If this environment variable is missing, the service
    cannot verify the policy and refuses to start.

    **To fix this:**

    1. Open [Sigil Warrant](https://sigilcore.com/tools/warrant)
    2. In Step 1, your public key is shown as `SIGIL_OPERATOR_PUBLIC_KEY=<value>`
    3. Copy that value and add it to your `.env.local` (development) or your
       production environment variables
    4. Restart the service

    If you have already generated your keypair and lost the public key value,
    you will need to generate a new keypair and re-sign your warranty.md.
    There is no way to recover the public key from a signed file alone.
  </Accordion>

  <Accordion title="My service failed to start. What does 'Signature verification failed' mean?">
    The warranty.md on disk has a `## signature` block, but the signature does
    not verify against the `SIGIL_OPERATOR_PUBLIC_KEY` in your environment. This
    means one of three things:

    1. **The policy file was modified after signing.** Even a single character
       change, including whitespace, invalidates the signature. Re-sign with
       Sigil Warrant and redeploy.
    2. **The wrong public key is set.** If you have rotated your keypair, the
       `SIGIL_OPERATOR_PUBLIC_KEY` in your environment must match the private key
       used to sign the current warranty.md.
    3. **The signature block was edited manually.** The `## signature` block is
       generated by Sigil Warrant and must not be edited. If you need to change
       your policy, edit the content above the signature block, then re-sign the
       entire file.

    Use the **Verify tab** in [Sigil Warrant](https://sigilcore.com/tools/warrant)
    to confirm a signed file is valid before deploying.
  </Accordion>

  <Accordion title="What is Sigil Warrant and why do I need it?">
    **Sigil Warrant** is the browser-based tool for issuing and signing your
    warranty.md policy file. It lives at
    [sigilcore.com/tools/warrant](https://sigilcore.com/tools/warrant).

    Sigil Warrant does three things:

    * Generates an Ed25519 keypair entirely in your browser. No key material
      leaves your machine
    * Lets you define your policy using a structured form with plain-English
      guidance for each field
    * Signs the policy content with your private key and produces a signed
      warranty.md for download

    The output is the signed warranty.md file and your `SIGIL_OPERATOR_PUBLIC_KEY`
    value. Both are required before sigil-sign will start.

    **Browser requirement:** Sigil Warrant requires Chrome 113+ or Safari 17+.
    If you prefer a CLI workflow, see the
    [CLI signing guide](https://docs.sigilcore.com) in the documentation.
  </Accordion>

  <Accordion title="I updated my policy. Do I need to re-sign it?">
    **Yes.** Every change to your warranty.md, including the version number,
    spend limits, allowed chains, or action list, invalidates the existing
    signature. You must re-sign with Sigil Warrant before redeploying.

    **Best practice:** Increment the `version` field (e.g. `1.0.0` → `1.1.0`)
    whenever you update your policy. This makes the new `policyHash` in
    subsequent attestations distinguishable from the previous version, which is
    useful for auditing and debugging.

    The Verify tab in Sigil Warrant lets you confirm a signed file is valid
    before you deploy it.
  </Accordion>

  <Accordion title="What is the policyHash in the Intent Attestation JWT?">
    Every approved attestation embeds a `policyHash` claim, the SHA-256 hex
    digest of your warranty.md content above the `## signature` block.

    This hash is your cryptographic proof that a specific policy version was in
    effect when the attestation was issued. It lets you verify, after the fact,
    that the correct policy governed a given agent action.

    You can see your policy's fingerprint in the **Step 4** output of Sigil
    Warrant after signing. Compare it to the `policyHash` in any attestation
    JWT to confirm the right policy was evaluated.
  </Accordion>

  <Accordion title="Does blocking bash commands block network access?">
    **No.** The `bash.blocked_commands` policy key checks the command string before the shell
    starts. It can deny a command whose declared text matches policy.
    Child-process network egress is not intercepted after shell execution
    begins. It is a command-string control, not a network control.

    For agents governed on SaaS surfaces, omit `bash` from `tool_calls.allowed`
    when the agent does not need a shell and allow only the required tool
    classes. If the agent requires `bash`, document the child-process network
    boundary, document the residual risk, and apply a separate network control.
  </Accordion>
</AccordionGroup>

***

## Data Privacy & Access

<AccordionGroup>
  <Accordion title="Can Sigil Sign read or collect my customer data?">
    **No.** Sigil Sign does not have access to your underlying customer data,
    files, database records, emails, prompts, or model context.

    Sigil Sign sits in the approval path, not your data plane. It only evaluates
    the authorization envelope your agent sends to `/v1/authorize`: agent ID,
    framework, chain ID, the requested action, target or tool fields needed for
    policy checks, optional metadata or context you choose to include, and the
    signed policy deployed for that API key.

    Do not put raw customer data in optional metadata or context unless your
    policy explicitly needs that value for enforcement.
  </Accordion>

  <Accordion title="Does Sigil Sign need credentials for my databases, files, email, or model provider?">
    **No.** Hosted Sigil Sign does not need database credentials, file-system
    access, email inbox access, cloud credentials, wallet keys, or model-provider
    credentials.

    Your agent or gateway asks Sigil Sign whether a proposed action is allowed.
    If the action complies with your signed policy, Sigil Sign returns a
    short-lived attestation. Your own runtime and key infrastructure still
    execute the action.
  </Accordion>

  <Accordion title="What does Sigil Sign store for audit and billing?">
    Hosted Sigil Sign stores the minimum operational records needed to meter,
    audit, and display enforcement decisions:

    * API key account metadata, including email, tier, hashed API key, and the
      deployed signed policy for that key
    * Usage events with API key ID, endpoint, timestamp, chain ID when
      applicable, decision, and the policy rule that triggered a denial or hold
    * Pending holds with a hash of the intent, method, agent ID, policy rule,
      policy hash, policy version, and expiry time
    * Operational logs for service health and debugging

    Sigil Sign does not store the full authorization request body for normal
    approve or deny decisions. Denial messages, webhook payloads, and logs can
    include the value that triggered a rule, such as a blocked path, URL,
    command string, recipient, or metadata field. Keep sensitive content out of
    enforcement fields unless the policy needs it.
  </Accordion>

  <Accordion title="Does Sigil use my prompts or customer data to train models?">
    **No.** Sigil Sign has no LLM in the enforcement path and does not train
    models on prompts, customer data, or authorization requests.

    The GRC Compiler is separate from Sigil Sign. If you upload compliance
    documents to generate a policy, those documents are processed only to return
    the policy output and are governed by the public Privacy Policy.
  </Accordion>

  <Accordion title="Who can see my enforcement records in Sigil Command?">
    Only the API key holder can see their own enforcement records. Sigil Command
    enforces tenant isolation on the server: every request is pinned to the API
    key ID from the authenticated session, and the client cannot override it.
  </Accordion>
</AccordionGroup>

***

## Errors & Policy Violations

<AccordionGroup>
  <Accordion title="Why was my transaction rejected with SIGIL_POLICY_VIOLATION?">
    A `SIGIL_POLICY_VIOLATION` means your proposed transaction was successfully
    processed, but it deterministically breached a rule in your `warranty.md`
    policy. **This is not a bug; it is the firewall working as intended.**

    **To diagnose:**

    1. Read the `message` or `reason` field in the JSON-RPC error response.
    2. Open your `warranty.md` and locate the breached constraint.
    3. Verify your request's `amount`, `targetAddress`, and `chainId` match the policy.

    *Do not retry the exact same transaction.* If the evaluation is
    deterministic, it will fail again. Fix the intent or the policy first.
    If you update the policy, re-sign it with Sigil Warrant before redeploying.

    **Code reference for the newer policy primitives:**

    * `SIGIL_POLICY_VIOLATION_NOT_ON_ALLOWLIST`: an `allow_only` field was missing or its value is not on the operator allowlist.
    * `SIGIL_POLICY_VIOLATION_TOKEN_NOT_ALLOWED`: the intent carried a `token` with no matching `token.<SYM>.*` rule (token intents fail closed).
    * `SIGIL_POLICY_VIOLATION_TOKEN_AMOUNT_EXCEEDED`: the token amount exceeds that token's `max_transaction`.
    * `SIGIL_POLICY_VIOLATION_TOKEN_AMOUNT_INVALID`: a token intent's `amount` was missing or unparseable; token amounts fail closed.
    * `SIGIL_POLICY_VIOLATION_BLOCKED_RECIPIENT`: an `email.send` recipient is on `email.blocked_recipients`.
    * `SIGIL_POLICY_VIOLATION_RECIPIENT_NOT_ALLOWED`: a recipient is missing or not on `email.allowed_recipients`.
    * `SIGIL_LOOP_LIMIT_EXCEEDED`: a `## execution_limits` tool-call ceiling was exceeded.
    * `SIGIL_MODEL_SPEND_LIMIT_EXCEEDED`: a `## execution_limits` model spend cap was exceeded.
    * `SIGIL_MODEL_TOKEN_LIMIT_EXCEEDED`: a `## execution_limits` model token cap was exceeded.
    * `SIGIL_MODEL_USAGE_UNAVAILABLE`: a policy declares a model budget cap, but the adapter did not report cumulative `intent.metadata.model_usage`.
    * `SIGIL_LIMIT_STORE_UNAVAILABLE`: Sigil could not read or increment the execution-limit counter, so it failed closed.
  </Accordion>

  <Accordion title="I'm getting SIGIL_VALIDATION errors. What's wrong?">
    `SIGIL_VALIDATION_*` errors mean your request failed schema validation
    before policy evaluation even began.

    **Common culprits:**

    * **`framework`:** Must be a non-empty string (lowercase alphanumeric and hyphens, max 64 chars). See the [Framework Registry](framework-registry) for known values. Unknown framework strings are accepted with a warning log.
    * **`txCommit`:** Must be a lowercase 64-character hex string. **Remove the `0x` prefix.**
    * **`chainId`:** Ensure you are targeting an allowlisted chain (1, 8453, 42161, 10, 137, 56, 999).
    * **`intent.action`:** Must match an entry in your warranty.md `allowed_actions`
      list (or the per-chain override for the requested chain).
  </Accordion>

  <Accordion title="What does the JSON-RPC error response look like?">
    Policy and validation failures on the `/rpc` and `/bundler` endpoints are
    returned as standard HTTP 200 JSON-RPC errors.

    Example:

    ```json theme={null}
    {
      "jsonrpc": "2.0",
      "id": 1,
      "error": {
        "code": -32602,
        "message": "SIGIL_POLICY_VIOLATION",
        "data": {
          "reason": "Sigil receipt required for write methods"
        }
      }
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Attestation Verification

<AccordionGroup>
  <Accordion title="My attestation expired before I could use it. What do I do?">
    Attestations expire exactly **60 seconds** from issuance. This strict window
    prevents replay attacks.

    1. Discard the expired token. It will be rejected.
    2. Request a new attestation by calling `POST /v1/authorize` again.
    3. Ensure your agent is not performing blocking operations (like heavy LLM
       reasoning) *between* receiving the attestation and submitting the
       transaction.
  </Accordion>

  <Accordion title="Can I cache and reuse an attestation for multiple transactions?">
    **No.** Attestations are single-use. They are cryptographically bound to a
    specific `txCommit` or `userOpHash`. Submitting an attestation with a
    different transaction hash will instantly fail validation.
  </Accordion>

  <Accordion title="How do I locally verify the Ed25519 signature?">
    Intent Attestations are standard Ed25519-signed JWTs. You can verify them
    using the `jose` library and Sigil's public JWK endpoint. Approved
    attestations also carry a parallel ML-DSA-65 post-quantum signature in the
    `pqc` claim; the classical verification below stays valid, and PQC-aware
    clients can additionally verify `pqc.sig` against the key set at
    `https://sign.sigilcore.com/v1/pqc-keys`.

    ```typescript theme={null}
    import { createRemoteJWKSet, jwtVerify } from "jose";

    const JWKS = createRemoteJWKSet(
      new URL("https://sign.sigilcore.com/.well-known/jwks.json")
    );
    const trustedIssuers = ["sigil-core"];

    const { payload } = await jwtVerify(intent_attestation, JWKS, {
      issuer: trustedIssuers,
      algorithms: ["EdDSA"],
    });

    // CRITICAL: Ensure payload.txCommit matches your transaction hash
    // ALSO CHECK: payload.policyHash matches your deployed policy fingerprint
    console.log(payload);
    ```

    For federated deployments, add explicitly approved issuer IDs to
    `trustedIssuers` and pair each issuer with its published JWKS endpoint.
  </Accordion>
</AccordionGroup>

***

## Sigil Command

<AccordionGroup>
  <Accordion title="What is Sigil Command?">
    Sigil Command is the read-only operator console for Sigil Sign. It displays
    a real-time violation log for every `DENIED`, `PENDING`, and `ALLOWED` policy
    enforcement event for your API key. It is available at
    [command.sigilcore.com](https://command.sigilcore.com).

    Command is included with every Sigil Sign API key, including the free
    Developer tier. No separate signup is required.
  </Accordion>

  <Accordion title="How do I sign in to Command?">
    Command uses **passwordless magic link authentication**:

    1. Go to [command.sigilcore.com](https://command.sigilcore.com)
    2. Enter the email address associated with your Sigil Sign API key
    3. Check your inbox for a magic link from `keys@sigilcore.com` (expires in 10 minutes)
    4. Click the link. Your browser creates a session (24-hour validity)

    If the email does not arrive, check your spam folder. The sender is
    `keys@sigilcore.com`.
  </Accordion>

  <Accordion title="Can I see other users' violations in Command?">
    **No.** Tenant isolation is enforced server-side. The API pins the
    `api_key_id` from your session JWT on every request; the client cannot
    override it. You can only see enforcement events for your own API key.
  </Accordion>

  <Accordion title="Can I edit or delete violations in Command?">
    **No.** Command is strictly read-only. Violation records are the
    authoritative audit trail of your policy enforcement and cannot be modified
    or deleted from the UI.
  </Accordion>

  <Accordion title="I don't see any violations. Is something broken?">
    If your violation log is empty, your agent has not triggered any policy
    enforcement events yet. To confirm the pipeline is working:

    1. Submit a test intent to `POST /v1/authorize` that intentionally breaches
       your warranty.md (e.g. exceed `max_transaction_eth` or use a blocked tool)
    2. The `DENIED` event should appear in Command within seconds

    If the denial still does not appear, verify your API key is active and the
    email you used to sign in matches the one on the key.
  </Accordion>
</AccordionGroup>

***

## Sigil Vault

<AccordionGroup>
  <Accordion title="What is Sigil Vault?">
    Sigil Vault is the **just-in-time (JIT) credential broker** for the Sigil
    ecosystem. It ensures that autonomous agents can use external credentials,
    such as API keys, cloud secrets, and MPC co-signatures, without ever possessing them.

    Vault is not a secrets manager. It does not store credentials. It intercepts
    agent requests via a localhost MITM proxy, validates a cryptographic Intent
    Attestation from Sigil Sign, fetches a short-lived credential from your own
    infrastructure (HashiCorp Vault, AWS, Azure, GCP), injects it into the
    outbound request, and purges it from memory.
  </Accordion>

  <Accordion title="Does Sigil Vault store my credentials?">
    **Never.** Vault is explicitly non-custodial. Credentials are fetched
    on-demand from your own backend infrastructure, injected into the outbound
    request, and immediately zeroed from memory. No credential persists in Vault
    between requests.

    Vault supports HashiCorp Vault, AWS Secrets Manager, AWS STS, Azure Key
    Vault, and GCP Secret Manager as credential sources. Your secrets stay in
    your infrastructure.
  </Accordion>

  <Accordion title="How does Vault relate to Sigil Sign?">
    Vault extends Sigil Sign's authorization model from on-chain execution to
    off-chain credential access. The flow is:

    1. Agent submits intent to Sigil Sign (`POST /v1/authorize`)
    2. Sigil Sign evaluates the intent against your warranty.md policy
    3. If approved, Sigil Sign issues an Ed25519 Intent Attestation
    4. Agent presents the attestation to Vault with its outbound request
    5. Vault validates the attestation, fetches the credential, and injects it

    Without a valid Intent Attestation, Vault does not release any credential.
  </Accordion>

  <Accordion title="What happens if the attestation is missing or invalid?">
    Vault has **zero fail-open paths**. A missing, invalid, expired, or replayed
    attestation results in a hard 403 rejection. There is no fallback, no
    degraded mode, and no bypass. An unknown or revoked agent token is also
    rejected. Backend timeouts return 504, never a blind passthrough.
  </Accordion>

  <Accordion title="Is Sigil Vault available now?">
    Vault is in **active development**. The architecture is finalized and
    implementation is underway. The MVP includes the MITM gateway, CLI
    management commands, credential backend adapters, and a local dashboard.

    See the [Sigil Vault component page](/components/sigil-vault) for the full
    Getting Started guide and architecture details.
  </Accordion>
</AccordionGroup>

***

## Key Custody & Security

<AccordionGroup>
  <Accordion title="Does Sigil store my private keys?">
    **Never.** Sigil is explicitly non-custodial.

    We do not hold your private keys, custody your treasury assets, or issue
    long-lived credentials to your agents. Sigil operates strictly as an
    authorization firewall. The agent proposes, Sigil authorizes, and your own
    key infrastructure (e.g., Fireblocks, AWS KMS) physically signs the
    transaction.

    Your warranty.md signing keypair, generated by Sigil Warrant, is also
    never transmitted to Sigil. The signing happens entirely in your browser.
    Sigil only receives your public key via `SIGIL_OPERATOR_PUBLIC_KEY`, which is
    used to verify your policy signature at startup.
  </Accordion>

  <Accordion title="What happens if I lose my warranty.md signing private key?">
    You cannot re-sign your existing policy without the private key. However,
    you can generate a new keypair at any time using Sigil Warrant.

    **Recovery steps:**

    1. Go to [sigilcore.com/tools/warrant](https://sigilcore.com/tools/warrant)
    2. Generate a new keypair in Step 1
    3. Re-enter your policy values (or use the Presets tab as a starting point)
    4. Sign and download the new warranty.md
    5. Update `SIGIL_OPERATOR_PUBLIC_KEY` in your environment to the new public key
    6. Deploy the new signed warranty.md
    7. Restart the service

    There is no way to recover a lost private key. The old keypair can be
    discarded. Your policy content is not secret, only the signature matters.
  </Accordion>
</AccordionGroup>
