Skip to content

Security & Auth

NeuralRepo is designed with security at every layer. This page covers authentication, authorization, encryption, and data isolation.

NeuralRepo supports four sign-in methods, all implemented using the Arctic OAuth library:

ProviderProtocolLibrary
GitHubOAuth 2.0Arctic
GoogleOpenID ConnectArctic
AppleSign In with Apple (OAuth 2.0)Custom (Apple requires server-side JWT)
Magic LinkEmail-basedCustom
  1. User clicks “Sign in with GitHub” (or Google/Apple).
  2. The server generates a state parameter and redirects to the provider.
  3. The provider authenticates the user and redirects back with an authorization code.
  4. The server exchanges the code for an access token and retrieves the user profile.
  5. If the email matches an existing user, the account is linked. Otherwise, a new user is created.
  6. A session is created and returned as an HttpOnly cookie.

For users who prefer email-based auth:

  1. User enters their email address.
  2. The server generates a one-time token, stores its SHA-256 hash in the magic_links table, and sends the token via email.
  3. The user clicks the link, which contains the token.
  4. The server hashes the token, looks up the matching record, validates expiry (15 minutes), and creates a session.
  5. The magic link record is deleted after use.

Sessions are the primary authentication mechanism for the web app.

PropertyValue
Token format32 random bytes, hex-encoded (64 characters)
StorageSHA-256 hash stored in D1 sessions table
Expiry30 days from creation
Cookie flagsHttpOnly, Secure, SameSite=Lax, Path=/
Auto-refreshSessions within 7 days of expiry are extended on active use

The raw session token is only ever sent to the client as a cookie. The server stores and compares only the SHA-256 hash. This means a database breach does not expose usable session tokens.

API keys provide programmatic access for the CLI, Siri Shortcuts, CI/CD, and custom integrations.

PropertyValue
Formatnrp_ prefix + 32 random bytes hex-encoded (64 hex chars)
StorageSHA-256 hash stored in D1 api_keys table
DisplayOnly the last 4 characters are shown after creation
RevocationImmediate — delete the key record

When a request includes an X-API-Key header:

  1. The server hashes the provided key with SHA-256.
  2. It looks up the hash in the api_keys table.
  3. If found, the request is authenticated as the key’s owner.
  4. The last_used_at timestamp is updated.

The full key is shown only once at creation time. It cannot be retrieved later.

User-provided AI keys (Anthropic, OpenAI, OpenRouter) are encrypted before storage:

PropertyValue
AlgorithmAES-256-GCM
Key sourceENCRYPTION_KEY environment variable (Workers secret)
IVRandom 12-byte IV generated per encryption
StorageBase64-encoded {iv}:{ciphertext}:{authTag} in D1

The encryption key is a Workers secret that never appears in code or logs. Decryption happens in-memory only when making an AI request, and the plaintext key is never written to disk or returned via API.

The MCP integration uses a full OAuth 2.0 with PKCE flow to authorize Claude’s access:

PropertyValue
Grant typeAuthorization Code with PKCE
Challenge methodS256 (SHA-256)
Authorization code expiry10 minutes
Access token expiry1 hour
Refresh token expiry90 days
Scopesideas:read, ideas:write

The PKCE flow prevents authorization code interception attacks. The MCP client generates a random code_verifier, hashes it to create a code_challenge, and sends the challenge with the authorization request. When exchanging the code for tokens, the server verifies the original verifier matches the stored challenge.

Refresh tokens are stored as SHA-256 hashes in the oauth_refresh_tokens table.

The API uses strict CORS configuration:

HeaderValue
Access-Control-Allow-Originhttps://neuralrepo.com (production)
Access-Control-Allow-MethodsGET, POST, PATCH, PUT, DELETE, OPTIONS
Access-Control-Allow-HeadersContent-Type, Authorization, X-API-Key
Access-Control-Allow-Credentialstrue
Access-Control-Max-Age86400 (24 hours)

The origin is restricted to the NeuralRepo web app domain. API key-authenticated requests (CLI, Siri, CI) do not use cookies and are not subject to CORS.

Rate limits are enforced using Cloudflare KV as a counter store:

Endpoint TypeLimit
General API60 requests/minute/user
Search30 requests/minute/user
Auth (login, magic link)10 requests/minute/IP
MCP tools60 requests/minute/user

When a limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header.

KV’s global replication ensures rate limits are consistent across edge locations. The counter key format is rate:{user_id}:{endpoint_group}:{minute_bucket} with a 120-second TTL.

Every database query in NeuralRepo is scoped by user_id:

SELECT * FROM ideas WHERE user_id = ? AND deleted_at IS NULL

There are no admin super-queries that bypass this filter in the production API. Each user’s data is completely isolated — you cannot access, search, or modify another user’s ideas regardless of the authentication method.