Incept5

eve-auth-and-secrets

Authenticate with Eve and manage project secrets for deployments and workflows.

Incept5 0 1 Updated 3mo ago
GitHub

Install

npx skillscat add incept5/eve-skillpacks/eve-auth-and-secrets

Install via the SkillsCat registry.

SKILL.md

Eve Auth and Secrets

Use this workflow to log in to Eve and manage secrets for your app.

When to Use

  • Setting up a new project profile
  • Authentication failures
  • Adding or rotating secrets
  • Secret interpolation errors during deploys
  • Setting up identity providers or org invites
  • Setting up access groups and scoped data-plane authorization
  • Configuring group-aware RLS for environment databases

Authentication

eve auth login
eve auth login --ttl 30                # custom token TTL (1-90 days)
eve auth status

Challenge-Response Flow

Eve uses challenge-response authentication. The default provider is github_ssh:

  1. Client sends SSH public key fingerprint
  2. Server returns a challenge (random bytes)
  3. Client signs the challenge with the private key
  4. Server verifies the signature and issues a JWT

Token Types

Type Issued Via Use Case
User Token eve auth login Interactive CLI sessions
Job Token Worker auto-issued Agent execution within jobs
Minted Token eve auth mint Bot/service accounts

JWT payloads include sub (user ID), org_id, scope, and exp. Verify tokens via the JWKS endpoint: GET /auth/jwks.

Permissions

Check what the current token can do:

eve auth permissions

Register additional identities for multi-provider access:

curl -X POST "$EVE_API_URL/auth/identities" -H "Authorization: Bearer $TOKEN" \
  -d '{"provider": "nostr", "external_id": "<pubkey>"}'

Identity Providers

Eve supports pluggable identity providers. The auth guard tries Bearer JWT first, then provider-specific request auth.

Provider Auth Method Use Case
github_ssh SSH challenge-response Default CLI login
nostr NIP-98 request auth + challenge-response Nostr-native users

Nostr Authentication

Two paths:

  • Challenge-response: Like SSH but signs with Nostr key. Use eve auth login --provider nostr.
  • NIP-98 request auth: Every API request signed with a Kind 27235 event. Stateless, no stored token.

Org Invites

Invite external users by identity hint:

# Admin creates invite targeting a Nostr pubkey
curl -X POST "$EVE_API_URL/auth/invites" -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"org_id": "org_xxx", "role": "member", "provider_hint": "nostr", "identity_hint": "<pubkey>"}'

When the pubkey authenticates, Eve auto-provisions their account and org membership.

Token Minting (Admin)

Mint tokens for bot/service users without SSH login:

# Mint token for a bot user (creates user + membership if needed)
eve auth mint --email app-bot@example.com --org org_xxx

# With custom TTL (1-90 days, default: server configured)
eve auth mint --email app-bot@example.com --org org_xxx --ttl 90

# Scope to project with admin role
eve auth mint --email app-bot@example.com --project proj_xxx --role admin

Print the current access token (useful for scripts):

eve auth token

Self-Service Access Requests

Users without an invite can request access:

eve auth request-access --org "My Company" --email you@example.com
eve auth request-access --org "My Company" --ssh-key ~/.ssh/id_ed25519.pub
eve auth request-access --status <request_id>

Admins approve or reject via:

eve admin access-requests list
eve admin access-requests approve <request_id>
eve admin access-requests reject <request_id> --reason "..."

List responses use the canonical { "data": [...] } envelope.

Approval is atomic (single DB transaction) and idempotent -- re-approving a completed request returns the existing record. If the fingerprint is already registered, Eve reuses that identity owner. If a legacy partial org matches the requested slug and name, Eve reuses it during approval. Failed attempts never leave partial state.

Credential Check

Verify local AI tool credentials:

eve auth creds                # Show Claude + Codex cred status
eve auth creds --claude       # Only Claude
eve auth creds --codex        # Only Codex

OAuth Token Sync

Sync local OAuth tokens into Eve secrets (scope: project > org > user):

eve auth sync                       # Sync to user-level
eve auth sync --org org_xxx         # Sync to org-level
eve auth sync --project proj_xxx    # Sync to project-level
eve auth sync --dry-run             # Preview without syncing

Access Groups + Scoped Access

Groups are first-class authorization primitives that segment data-plane access (org filesystem, org docs, environment databases). Create groups, add members, and bind roles with scoped constraints:

# Create a group
eve access groups create --org org_xxx --slug eng-team --name "Engineering"

# Add members
eve access groups members add eng-team --org org_xxx --user user_abc
eve access groups members add eng-team --org org_xxx --service-principal sp_xxx

# Bind a role with scoped access
eve access bind --org org_xxx --group grp_xxx --role data-reader \
  --scope-json '{"orgfs":{"allow_prefixes":["/shared/"]},"envdb":{"schemas":["public"]}}'

# Check effective access
eve access memberships --org org_xxx --user user_abc

Scope Types

Resource Scope Fields Example
Org Filesystem orgfs.allow_prefixes, orgfs.read_only_prefixes "/shared/", "/reports/"
Org Documents orgdocs.allow_prefixes, orgdocs.read_only_prefixes "/pm/features/"
Environment DB envdb.schemas, envdb.tables "public", "analytics_*"

Group-Aware RLS

Scaffold RLS helper functions for group-based row-level security in environment databases:

eve db rls init --with-groups

This creates SQL helpers (app.current_user_id(), app.current_group_ids(), app.has_group()) that read session context set by Eve's runtime. Use them in RLS policies:

CREATE POLICY notes_group_read ON notes FOR SELECT
  USING (group_id = ANY(app.current_group_ids()));

Membership Introspection

Inspect a principal's full effective access -- base org/project roles, group memberships, resolved bindings, and merged scopes:

eve access memberships --org org_xxx --user user_abc
eve access memberships --org org_xxx --service-principal sp_xxx

The response includes effective_scopes (merged across all bindings), effective_permissions, and each binding's matched_via (direct or group).

Resource-Specific Access Checks

Check and explain access against a specific data-plane resource:

eve access can orgfs:read /shared/reports --org org_xxx
eve access explain orgfs:write /shared/reports --org org_xxx --user user_abc

The response includes scope_required, scope_matched, and per-grant scope_reason explaining why a binding did or did not match the requested resource path.

Policy-as-Code (v2)

Declare groups, roles, and scoped bindings in .eve/access.yaml. Use version: 2:

version: 2
access:
  groups:
    eng-team:
      name: Engineering Team
      description: Scoped access for engineering collaborators
      members:
        - type: user
          id: user_abc
  roles:
    app_editor:
      scope: org
      permissions:
        - orgdocs:read
        - orgdocs:write
        - orgfs:read
        - envdb:read
  bindings:
    - subject: { type: group, id: eng-team }
      roles: [app_editor]
      scope:
        orgdocs: { allow_prefixes: ["/groups/app/**"] }
        orgfs: { allow_prefixes: ["/groups/app/**"] }
        envdb: { schemas: ["app"] }

Validate, plan, and sync:

eve access validate --file .eve/access.yaml
eve access plan --file .eve/access.yaml --org org_xxx
eve access sync --file .eve/access.yaml --org org_xxx

Sync is declarative: it creates, updates, and prunes groups, members, roles, and bindings to match the YAML. Invalid scope configurations fail fast before any mutations are applied. Binding subjects can be user, service_principal, or group.

Key Rotation

Rotate the JWT signing key:

  1. Set EVE_AUTH_JWT_SECRET_NEW alongside the existing secret
  2. Server starts signing with the new key but accepts both during the grace period
  3. After grace period (EVE_AUTH_KEY_ROTATION_GRACE_HOURS), remove the old secret
  4. Emergency rotation: set only the new key (immediately invalidates all existing tokens)

Project Secrets

# Set a secret
eve secrets set API_KEY "your-api-key" --project proj_xxx

# List keys (no values)
eve secrets list --project proj_xxx

# Delete a secret
eve secrets delete API_KEY --project proj_xxx

# Import from file
eve secrets import .env --project proj_xxx

Secret Interpolation

Reference secrets in .eve/manifest.yaml using ${secret.KEY}:

services:
  api:
    environment:
      API_KEY: ${secret.API_KEY}

Manifest Validation

Validate that all required secrets are set before deploying:

eve manifest validate --validate-secrets    # check secret references
eve manifest validate --strict              # fail on missing secrets

Local Secrets File

For local development, create .eve/dev-secrets.yaml (gitignored):

secrets:
  default:
    API_KEY: local-dev-key
    DB_PASSWORD: local-password
  staging:
    DB_PASSWORD: staging-password

Worker Injection

At job execution time, resolved secrets are injected as environment variables into the worker container. File-type secrets are written to disk and referenced via EVE_SECRETS_FILE. The file is removed after the agent process reads it.

Git Auth

The worker uses secrets for repository access:

  • HTTPS: github_token secret → Authorization: Bearer header
  • SSH: ssh_key secret → written to ~/.ssh/ and used via GIT_SSH_COMMAND

Troubleshooting

Problem Fix
Not authenticated Run eve auth login
Token expired Re-run eve auth login (tokens auto-refresh if within 5 min of expiry)
Bootstrap already completed Use eve auth login (existing user) or eve admin invite (new users). On non-prod stacks, eve auth bootstrap auto-attempts server recovery. For wrong-email recovery: eve auth bootstrap --email correct@example.com
Secret missing Confirm with eve secrets list and set the key
Interpolation error Verify ${secret.KEY} spelling; run eve manifest validate --validate-secrets
Git clone failed Check github_token or ssh_key secret is set
Service can't reach API Verify EVE_API_URL is injected (check eve env show)
Scoped access denied Run eve access explain <permission> <resource> --org <org> to see scope match details. Check that the binding's scope constraints include the target path/schema

Incident Response (Secret Leak)

If a secret may be compromised:

  1. Contain: Rotate the secret immediately via eve secrets set
  2. Invalidate: Redeploy affected environments
  3. Audit: Check eve job list for recent jobs that used the secret
  4. Recover: Generate new credentials at the source (GitHub, AWS, etc.)
  5. Document: Record the incident and update rotation procedures