# How API Keys Are Securely Stored in Maka's Credential Vault: A Deep Dive into Apache Maka's Security Model

> Learn how Maka securely stores API keys in its credential vault using OS-level file permissions, size limits, and runtime access controls to protect sensitive data.

- Repository: [The Apache Software Foundation/maka](https://github.com/apache/maka)
- Tags: deep-dive
- Published: 2026-09-09

---

**Maka stores API keys in a per-workspace [`credential-vault.json`](https://github.com/apache/maka/blob/main/credential-vault.json) file located in the Electron user-data directory, enforcing OS-level file permissions, size limits, and strict runtime access controls to prevent UI exposure.**

The Apache Maka project implements a **credential vault** system designed to keep sensitive secrets like API keys confidential and isolated from the renderer process. Unlike cloud-based secret managers, Maka adopts a local-first approach where credentials persist only on the user's machine under strict operational constraints.

## The Credential Vault Architecture

Maka's credential storage centers on the `CredentialVaultDocumentOwner` class, which manages a JSON-based vault file that never leaves the local workspace.

### File Location and Permissions

The vault file resides in the Electron user-data directory under the specific workspace path:

```bash
…/workspaces/default/credential-vault.json

```

This location benefits from intrinsic operating system protections: the file inherits the OS account permissions of the running Maka process, meaning only the user executing the application can read the contents. As documented in the repository's README, this file remains excluded from version control and never synchronizes to remote repositories.

### Vault Structure and Entry Format

Each secret stored in the vault follows the `CredentialVaultEntry` interface defined in [`packages/storage/src/runtime-policy/credential-vault-document.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/runtime-policy/credential-vault-document.ts). An entry contains:

- **locator**: A descriptor object identifying the credential scope, kind, and provider
- **credentialId**: A unique UUID generated via `randomUUID()`
- **revision**: An incrementing version number for optimistic concurrency
- **secret**: The raw API key or token stored as a plain string
- **updatedAt**: A timestamp marking the last modification

The vault document itself maintains a bounded size enforced by the `VAULT_DOCUMENT_MAX_BYTES` constant, preventing unbounded growth that could impact performance or storage.

## Writing Secrets to the Vault

The `CredentialVaultDocumentOwner.set()` method serves as the primary interface for persisting new API keys or updating existing ones.

### Input Validation and Size Limits

Before committing any secret to disk, Maka enforces strict validation rules. The system rejects any secret exceeding **64 KB** in length, protecting against buffer overflow attacks and accidental paste errors:

```ts
// packages/storage/src/runtime-policy/credential-vault-document.ts
const FILE = 'credential-vault.json';                     // ← vault file name
const MAX_SECRET_LENGTH = 64 * 1024;                     // ← secret size limit

```

If the input passes length validation, the `prepareSet` routine constructs a `CredentialVaultEntry` with either incremented revision metadata for updates or fresh UUID and revision fields for new entries.

### The set() Method Workflow

The complete write operation follows this sequence:

```ts
async set(root: string, rawInput: SetCredentialInput) {
  const prepared = this.prepareSet(await this.read(root), rawInput);
  if (prepared.kind !== 'ready') return prepared;
  await this.commitSet(root, prepared);                 // writes JSON document
  return committed(prepared.document);
}

```

Persistence occurs through the private `write()` method, which delegates to `writeJsonDocument` for atomic file operations. This low-level helper, defined in [`packages/storage/src/runtime-policy/document-io.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/runtime-policy/document-io.ts), guarantees that writes either complete successfully or leave the existing vault intact, preventing corruption during system crashes:

```ts
private async write(root: string, document: CredentialVaultDocument) {
  this.assertDocumentSize(document);
  await writeJsonDocument(root, FILE, document, VAULT_DOCUMENT_MAX_BYTES);
}

```

## Runtime Access Controls

Maka distinguishes between the **UI layer** (renderer process) and **runtime operations** (main process), ensuring that raw secrets never traverse process boundaries unnecessarily.

### How Secrets Are Retrieved

When runtime components require credential material, they invoke the `credentialMaterial()` utility function rather than accessing the vault entry directly:

```ts
export function credentialMaterial(entry: CredentialVaultEntry): RuntimePolicyCredentialMaterial {
  return deepFreeze({ ...credentialBasis(entry), secret: entry.secret });
}

```

This function returns a `RuntimePolicyCredentialMaterial` object containing the secret, but only within the short-lived scope of the runtime operation. The use of `deepFreeze()` prevents accidental mutation of the credential object after creation.

### UI Isolation Guarantees

The architecture explicitly prevents the Electron renderer process from ever receiving the raw secret value. When the UI needs to display credential metadata—such as which API keys are configured—it receives only the `credentialBasis()` data (locator, ID, revision, and timestamps) without the `secret` field. This architectural boundary ensures that XSS attacks or compromised renderer processes cannot extract API keys from memory.

## Security Layers and Protections

Maka implements a defense-in-depth strategy through three concrete mechanisms:

- **File-system isolation**: The [`credential-vault.json`](https://github.com/apache/maka/blob/main/credential-vault.json) file resides in the OS-protected Electron user-data folder, readable only by the account running Maka.
- **Size and format limits**: Secrets longer than 64 KB are rejected, and the total vault document size is capped to prevent resource exhaustion.
- **Controlled access patterns**: Raw secrets flow only through `credentialMaterial()` during runtime operations, maintaining strict separation from the UI layer.

## Summary

- API keys persist locally in [`credential-vault.json`](https://github.com/apache/maka/blob/main/credential-vault.json) within the Electron user-data directory, protected by OS file permissions.
- The `CredentialVaultDocumentOwner.set()` method enforces a 64 KB maximum secret size and writes data atomically via `writeJsonDocument`.
- Vault entries track UUIDs, revision numbers, and timestamps to support optimistic concurrency.
- The `credentialMaterial()` function exposes secrets only to runtime processes, never to the UI renderer.
- Size constraints at both the secret level (`MAX_SECRET_LENGTH`) and document level (`VAULT_DOCUMENT_MAX_BYTES`) prevent abuse.

## Frequently Asked Questions

### Where does Maka store API keys on disk?

Maka stores API keys in a file named [`credential-vault.json`](https://github.com/apache/maka/blob/main/credential-vault.json) located within the Electron user-data directory under the active workspace path (e.g., `…/workspaces/default/credential-vault.json`). This location ensures that only the operating system user running Maka can access the file, and the file never syncs to version control or cloud storage.

### What is the maximum size for a secret in Maka?

Maka rejects any secret longer than 64 KB (65,536 bytes) through the `MAX_SECRET_LENGTH` constant defined in [`credential-vault-document.ts`](https://github.com/apache/maka/blob/main/credential-vault-document.ts). Additionally, the entire vault document cannot exceed `VAULT_DOCUMENT_MAX_BYTES`, protecting against storage abuse or accidental database corruption from oversized entries.

### How does Maka prevent the UI from accessing API keys?

The architecture enforces a strict boundary where the Electron renderer process never receives raw secret values. The `credentialMaterial()` function only executes within the main/runtime process, returning frozen objects containing secrets exclusively to runtime operations. The UI layer can query for credential existence and metadata but receives entries processed through `credentialBasis()`, which omits the `secret` field entirely.

### Is the credential vault encrypted?

According to the current Apache Maka source code, the credential vault stores secrets as plain text in the JSON file. Security relies on OS-level file permissions restricting access to the user account and the architectural isolation preventing secret exposure to the UI process. The repository does not currently implement application-level encryption at rest for the vault file.