Every request is checked the same way: who is calling, which workspace, what their role allows, and whether the resource belongs to that workspace's project. An id from another workspace answers 404, exactly like an id that does not exist, before any of its data is read.
What Harakumo staff can and cannot see, how long each kind of record is kept, and what is still being switched on are on the Security page: harakumo.com/security.
Your account
- Two-factor sign-in: Settings → Account. Scan the code with an authenticator app, confirm a code, and keep the recovery codes. Sign-in then asks for a code (the API answers
{ mfaRequired, ticket }; complete withPOST /api/auth/login/mfa { ticket, code | recoveryCode }). Turning it off needs your password and a code. - Changing your email needs your current password (and a code when two-factor is on), then a code sent to the new address. The old address is told.
- A password reset or change signs out your other sessions and disconnects AI connectors. A reset code lasts 15 minutes and allows 5 tries; asking again keeps the codes already sent working (the newest three), and one account is sent at most three codes in 15 minutes. The email's button opens the second step with the code filled in.
- Sessions last 30 days; Settings lists them and signs the others out.
- Changes made with the dashboard cookie are refused when they come from another site, and so is signing out: another site cannot sign you out.
- Download a copy of what Harakumo keeps about you as a person in Settings → Account (Your data): your account, two-factor status, workspaces and roles, sign-ins, connected AI assistants, the API keys you made, invitations, messages you sent us and your most recent 5,000 actions, as a JSON file with no secret or hash of one in it. It takes you signed in to the dashboard (
GET /api/auth/me/export; an AI connector or API key gets 403dashboard_only), at most five times an hour, and each download is written in your workspace's activity and emailed to you. - An account Harakumo suspends (for abuse, for example) is refused everywhere with 403
account_suspended, its sessions and AI connectors included, and so are the API keys it made (key_creator_suspended). Nothing in it is deleted, and the refusal says where to ask why.
Keys and connectors
- API keys can be read-only, limited to one project, or both (see API keys & authentication). Give each app the narrowest key that works, give keys an expiry date, and pause one you suspect has leaked while you replace it.
- An owner can require two-factor sign-in of every member of the workspace (see Workspaces → Requiring two-factor sign-in).
- AI connectors are connected read-only or read-and-manage; a read-only connector cannot change anything. Changes still ask you first in the assistant.
- No key or connector can change your email, password or sessions, accept invitations, or move money out — those need you in a browser.
- Revoke keys in Settings → API access and connectors in Dashboard → Connectors; both take effect immediately.
How your data is kept apart
| Layer | Separation |
|---|---|
| Every API call | Your credential resolves to one workspace; resources are found through project → workspace, never by id alone. |
| Databases | Each database is its own SQLite database. SQL in one can never reach another. |
| Storage | Each bucket is its own bucket in object storage; a signed URL is for one key in one bucket. |
| Vector DB | One index per collection. |
| Memory | Rows in Harakumo's control database, keyed by store and scope; searches never cross scopes. |
| Functions | Each runs as its own isolated edge program with only its project's environment variables and no access to platform storage. |
| Static sites | Served by a Harakumo-written program that reads only its own deployment's files and keeps its own edge cache under a secret name. A site gets changes to this program, such as its own cache and its HTTPS redirect, when it is published again or when Harakumo refreshes every live site. |
| Server apps | Each deployment runs in its own container. |
| Auth pools | One per project, with its own signing secret. |
| Payments | Buyers pay into Harakumo's processor account; each project's share is tracked in a ledger, and withdrawals go only to the payout account the workspace owner connected. |
| Each workspace sends from no-reply@harakumo.com or from its own verified domains (a domain belongs to one workspace), with its own log and suppression list. | |
| Domains | Each root domain has one owning workspace; no other workspace can add a hostname under it. |
How secrets are stored
- Passwords (yours and your end users'): PBKDF2 hashes.
- Sessions, API keys, connector tokens and auth-pool client secrets: SHA-256 hashes; the plaintext is shown once.
- Two-factor recovery codes: hashed, and each works once.
- Environment variables, auth-pool JWT secrets and payment webhook secrets: kept, because they are injected into deploys and used to sign tokens and events. Never shown to viewers or read-only keys, and the AI connector never returns environment variable values or webhook secrets. Encrypting them with a key kept outside the database is being switched on; until it is, they are stored readable.
- An auth pool's JWT secret is returned once to whoever enables the pool (
POST /api/projects/:id/auth), so the app can store it: a developer in the dashboard or a full-access API key. When an AI assistant enables the pool through the connector (enable_authorsetup_app_backend), the JWT secret and the client secret are stored as the project's environment variablesHARAKUMO_AUTH_JWT_SECRETandHARAKUMO_AUTH_CLIENT_SECRETinstead, and the assistant gets only their names. After that, developers and up, full-access API keys included, can show the JWT secret again (GET /api/auth-pools/:id/secret), and each reveal is audited. - Authenticator secrets (two-factor): stored readable until sealing them with a separate key is switched on.
Security checks
Your workspace's security checks are on Dashboard → Shield: a score, and what each check found in the workspace's own records. Shield → Security checks says what each one measures.
Reference
REST
POST /api/auth/login { "email", "password" } → session, or { mfaRequired, ticket }
POST /api/auth/login/mfa { "ticket", "code" | "recoveryCode" }
GET|POST|PUT|PATCH|DELETE /api/auth/mfa # status, set up, confirm, new recovery codes, turn off (browser session)
GET /api/auth/sessions · DELETE # sign out other sessions
GET /api/auth/me/export # a copy of your personal data (browser session)
GET /api/security/overview # the workspace's security checks