Skip to main content

Credentials — Encrypted Secret Storage

Credentials let you store encrypted secrets for external services in one place and reference them from agents, skills, and integrations. Instead of scattering API keys across your configuration, you define a credential once and FleetQ injects it at execution time — never exposing the raw secret in logs or agent prompts.

Scenario: A research agent calls the OpenAI API, a CRM connector, and a Slack webhook. Each service needs its own secret. With Credentials, you configure each secret once and reference them by name — rotation, expiry, and access auditing happen automatically.

Credential types

Type Use case
api_token Single API key or bearer token for a service (OpenAI, Anthropic, SendGrid, …). Stored in secret_data.token.
basic_auth Username and password for HTTP Basic Authentication. Required fields: username, password.
ssh_key SSH private key material for git and shell tools. Required field: private_key.
oauth2 OAuth 2.0 tokens. Stores access_token and optionally refresh_token, client_id, client_secret.
proxy HTTP/HTTPS/SOCKS5 proxy definition with optional username and password. Assign to a Tool via transport_config.proxy_credential_id to route that tool's outbound traffic through the proxy — used with the browser sandbox headful mode for residential-proxy anti-bot scenarios. Chromium SOCKS5 with auth is handled by a local gost forwarder.
custom_kv Arbitrary key-value pairs in secret_data. Use for services with non-standard auth formats.

Security & encryption

FleetQ uses per-team envelope encryption to protect all credential secrets at rest.

  • Each team has a unique Data Encryption Key (DEK) generated automatically on team creation.
  • The DEK itself is wrapped with the platform's APP_KEY (AES-256-CBC via Laravel's encryption layer).
  • Secrets are encrypted using XSalsa20-Poly1305 (libsodium) with the team's DEK — a different nonce per secret.
  • Secrets are decrypted only at execution time, in memory, and are never written to logs or stored in plaintext.
  • Every decryption is recorded in the audit log (audit_entries table) for compliance.
Rotating the APP_KEY requires re-encrypting team DEKs. Use the credentials:re-encrypt Artisan command to batch-migrate all secrets to a new key.

Optional KMS wrappers. For teams with stricter compliance requirements, the DEK can be wrapped by an external Key Management Service instead of the platform's APP_KEY. FleetQ ships adapters for AWS KMS, Azure Key Vault, and Google Cloud KMS via app/Infrastructure/Encryption/KMS. Enable a KMS wrapper by pointing the team at a managed key ARN/URI in Team Settings — existing credentials are re-wrapped on the next rotation.

Credential statuses

Active

Credential is valid and will be injected at execution time.

Disabled

Manually disabled. Will not be injected until re-enabled.

Expired

Past the expires_at date. Auto-transitioned by the scheduler.

Revoked

Permanently invalidated. Cannot be re-enabled — create a new credential instead.

Creating credentials

Navigate to Credentials → New Credential in the sidebar, or use the API. Required fields:

  • Name — human-readable label (e.g., OpenAI Production Key).
  • Type — one of the six credential types above.
  • Secret data — JSON object with the actual secret values (see example below).
  • Description (optional) — notes about the credential's purpose or scope.
  • Expires at (optional) — ISO 8601 date. FleetQ auto-expires the credential when this date passes.
secret_data examples by type
// api_token
{ "token": "sk-abc123..." }

// basic_auth
{ "username": "admin", "password": "hunter2" }

// ssh_key
{ "private_key": "-----BEGIN OPENSSH PRIVATE KEY-----\n..." }

// oauth2
{
  "access_token": "ya29.abc...",
  "refresh_token": "1//0g...",
  "client_id": "my-app",
  "client_secret": "secret"
}

// custom_kv
{ "account_id": "ACC-9001", "api_secret": "xyz", "region": "us-east-1" }

// proxy
{
  "protocol": "socks5",
  "host": "proxy.example.net",
  "port": 1080,
  "username": "fleetq",
  "password": "s3cret"
}
Never paste secrets into the Name or Description fields — those are stored in plaintext. Always use secret_data for sensitive values.

Secret rotation

Use Rotate Secret from the credential detail page (or POST /api/v1/credentials/{id}/rotate) to update the secret without deleting and recreating the credential. The RotateCredentialSecretAction:

  • Atomically replaces secret_data with the new value.
  • Re-encrypts under the team's current DEK.
  • Logs the rotation to the audit trail (old value is never stored).
  • Preserves the credential's UUID — existing agent/skill references remain valid.
Rotate via API
curl -X POST https://your-instance.com/api/v1/credentials/cred-uuid-here/rotate \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "secret_data": { "key": "sk-new-key-here" } }'

Project credentials

Credentials can be scoped to specific projects. The ResolveProjectCredentialsAction collects all credentials associated with a project and injects them into agent executions as named environment variables. This allows different projects to use different API keys for the same service without modifying agent configuration.

Attach credentials to a project from the project detail page under the Credentials tab. At execution time, FleetQ decrypts and injects only the credentials assigned to that project — other team credentials remain inaccessible.

BYOK — Bring Your Own LLM Keys

Teams can supply their own LLM provider API keys instead of relying on platform defaults. Configure BYOK keys in Team Settings → Provider Credentials.

The ProviderResolver selects the active LLM key using the following priority hierarchy:

Skill
Agent
Team BYOK
Platform Default
  • A skill-level override takes highest precedence (set per skill version).
  • An agent-level override applies to all skills executed by that agent.
  • Team BYOK keys apply across the team when no skill/agent override is set.
  • The platform default (configured via .env) is used as the fallback.
BYOK keys are stored as TeamProviderCredential records, encrypted with the same per-team XSalsa20-Poly1305 scheme as regular credentials.

MCP tools

The FleetQ MCP server exposes the following tools for credential management — accessible to any LLM agent with a valid session.

Tool Description
credential_list List all credentials for the team with optional status filter.
credential_get Retrieve credential metadata by ID (secret values are never returned).
credential_create Create a new credential with name, type, secret_data, and optional expiry.
credential_update Update credential metadata (name, description, expires_at, status).
credential_rotate Replace the secret_data atomically. Preserves all references to the credential.
credential_oauth_initiate Begin an OAuth2 authorization code flow — returns the redirect URL.
credential_oauth_finalize Exchange the OAuth2 callback code for tokens and store them encrypted.

API endpoints

All endpoints require a Sanctum bearer token and respect team scope. Full OpenAPI schema available at /docs/api.

Method Path Description
GET /api/v1/credentials List credentials. Filter by status or type. Cursor-paginated.
GET /api/v1/credentials/{id} Get a single credential. Secret values are omitted from the response.
POST /api/v1/credentials Create a new credential. Pass name, type, secret_data, and optionally expires_at.
PUT /api/v1/credentials/{id} Update credential metadata. Use /rotate to change secrets.
DELETE /api/v1/credentials/{id} Delete a credential. This is permanent and cannot be undone.
POST /api/v1/credentials/{id}/rotate Replace secret values atomically. Pass the full new secret_data object.
Deleting a credential that is actively referenced by an agent or project will cause execution failures. Prefer setting the status to disabled while you migrate references, then delete.