AnyaSelf Docs

Security & Trust Model

Authentication, authorization, internal trust, and purchase flow hardening.

AnyaSelf handles family finances (purchase approvals, checkout confirmation) and personal data (wardrobe, style preferences). This page documents the security architecture.

Authentication Architecture

graph LR
  subgraph Client
    APP["React SPA"]
  end

  subgraph External
    OIDC["OIDC Provider<br/>(Firebase Auth / Google)"]
  end

  subgraph AnyaSelf
    GW["API Gateway :8080"]
    SERVICES["Downstream Services"]
  end

  APP -- "1. Login via provider SDK" --> OIDC
  OIDC -- "2. ID Token" --> APP
  APP -- "3. POST /auth/login { idToken }" --> GW
  GW -- "4. Verify token via JWKS" --> OIDC
  GW -- "5. Mint internal JWT" --> APP
  APP -- "6. Bearer {internalJWT}" --> GW
  GW -- "7. Forward principal" --> SERVICES

JWT Model

EnvironmentAlgorithmSecret Source
DevelopmentHS256Shared AUTH_JWT_SECRET (default: dev-secret-change-me)
ProductionRS256OIDC/JWKS from AUTH_EXTERNAL_JWKS_URL

In production, the default dev-secret-change-me is rejected at startup to prevent accidental deployment with weak credentials.

Token Lifecycle

  1. Client authenticates with an external OIDC provider (Firebase Auth, Google)
  2. Client sends the external idToken to POST /auth/login
  3. Gateway verifies the token against the provider's JWKS endpoint
  4. Gateway mints an internal AnyaSelf bearer token with AUTH_ACCESS_TOKEN_TTL_SECONDS (default: 3600s)
  5. Internal token contains sub (userId) and email claims

Internal Trust Model

Microservices authenticate machine-to-machine calls using shared X-Internal-Token headers.

TokenServicesPurpose
ORCHESTRATOR_INTERNAL_TOKENorchestrator ↔ hyperbeam-bridge, orchestrator ↔ artifacts-auditBridge events, artifact writes
BUYFLOW_INTERNAL_TOKENorchestrator → api-gatewaycart-ready and failed purchase transitions

[!WARNING] In production, set REQUIRE_INTERNAL_EVENT_TOKEN=true and REQUIRE_BUYFLOW_INTERNAL_TOKEN=true. Without these, internal endpoints are unprotected.

Purchase Flow Hardening

The buy-flow is the most security-critical path because it involves real money.

sequenceDiagram
    participant U as User
    participant GW as API Gateway

    U->>GW: POST /requests (create)
    Note over GW: Status: SUBMITTED
    U->>GW: POST /requests/{id}/approve
    Note over GW: Status: APPROVED

    U->>GW: POST /requests/{id}/purchase-intents
    Note over GW: Mint ephemeral confirmationToken<br/>TTL: 900s (CHECKOUT_CONFIRMATION_TTL_SECONDS)

    Note over U: confirmationToken held in memory only<br/>NEVER in localStorage/sessionStorage

    U->>GW: POST /requests/{id}/confirm-checkout<br/>{intentId, confirmationToken}
    Note over GW: Verify token + TTL → Status: COMPLETED

Key Safeguards

  1. Actor binding: cart-ready and failed transitions are bound to the user who created the purchase intent
  2. Ephemeral confirmation token: Minted on intent creation, valid for CHECKOUT_CONFIRMATION_TTL_SECONDS (default 900s)
  3. Memory-only token storage: Frontend must never persist the confirmation token to localStorage or sessionStorage
  4. Internal token gate: cart-ready and failed endpoints require X-Internal-Token when REQUIRE_BUYFLOW_INTERNAL_TOKEN=true

Data Scoping

All AnyaSelf data is scoped to the Household resource:

  • Every API path includes {householdId} as a path parameter
  • JWT principal must be a member of the household to access its data
  • Household deletion (DELETE /households/{id}) cascades to all members, items, outfits, requests, and audit logs

Rate Limiting

EndpointLimitWindow
POST /voice/live/public-sessionVOICE_LIVE_PUBLIC_RATE_LIMIT_MAX_REQUESTS (default: 12)VOICE_LIVE_PUBLIC_RATE_LIMIT_WINDOW_SECONDS (default: 60s)

Rate limiting is IP-based, resolved via X-Forwarded-For header.

Hyperbeam Event Signatures

When HYPERBEAM_ENFORCE_EVENT_SIGNATURES=true, the Chrome Extension running inside Hyperbeam sessions must sign events with an HMAC using HYPERBEAM_EVENT_SIGNING_SECRET. Unsigned or incorrectly signed events are rejected.

On this page