# Schema for Transactions in Claude-Obsidian: The Complete Developer Guide

> Understand the Claude-Obsidian transaction schema. Learn about BUNDLE_SCHEMA, RESULT_SCHEMA, and JOURNAL_SCHEMA for atomic vault modifications.

- Repository: [Agrici.Daniel/claude-obsidian](https://github.com/AgriciDaniel/claude-obsidian)
- Tags: developer-guide
- Published: 2026-08-25

---

**Claude-Obsidian defines three JSON schemas—`BUNDLE_SCHEMA`, `RESULT_SCHEMA`, and `JOURNAL_SCHEMA`—that govern how atomic, recoverable vault modifications are structured, validated, and persisted.**

The open-source [AgriciDaniel/claude-obsidian](https://github.com/AgriciDaniel/claude-obsidian) repository implements a strict transaction system to ensure safe, auditable changes to Obsidian vaults. Understanding the schema for transactions in Claude-Obsidian is essential for developers building automation tools, CLI integrations, or custom vault workflows that require deterministic rollback capabilities.

## The Three Core Transaction Schemas

The transaction system relies on three distinct schema constants defined at the top of [`claude_obsidian/transaction.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py) (lines 41–43). Each serves a specific purpose in the transaction lifecycle:

- **`BUNDLE_SCHEMA`** (`"claude-obsidian.transaction.v1"`): The top-level JSON structure submitted to the system containing operation metadata, file writes, and optional backups.
- **`RESULT_SCHEMA`** (`"claude-obsidian.transaction-result.v1"`): The JSON object returned after transaction completion, recording final state, bundle hashes, and diagnostics.
- **`JOURNAL_SCHEMA`** (`"claude-obsidian.transaction-journal.v1"`): The persistent audit log stored under `.vault-meta/transactions/<operation_id>/journal.json`, enabling deterministic recovery.

## Anatomy of a Transaction Bundle

A transaction bundle is a Python `dict` that must include the `schema` field set to `BUNDLE_SCHEMA`. The structure enforces atomic, recoverable updates through carefully validated fields.

### Operation Metadata and Validation

Every bundle requires two critical identifier fields validated by specific helper functions:

- **`operation_id`**: A filesystem-safe string validated by `safe_operation_id()` (lines 35–51 in [`claude_obsidian/transaction.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py)).
- **`operation_type`**: Must be one of the values in `OPERATION_TYPES` (e.g., `"save"`, `"ingest"`, `"autoresearch"`) defined at lines 44–58.

### Write Specifications

The `writes` array contains dictionaries specifying each file modification. Each entry includes:

```json
{
  "path": "wiki/notes/example.md",
  "mode": 0o644,
  "content_sha256": "<hash of new content>",
  "original_sha256": null
}

```

Path validation occurs through `_normalize_vault_path` and `_assert_portable_write_path` (lines 54–86 and 88–104), ensuring writes remain confined to the vault directory and follow portable naming conventions.

### Optional Backups

The `backups` field accepts an optional list of backup descriptors, allowing the system to preserve existing state before applying changes.

## Transaction Results and Journal Persistence

After applying a bundle, the system returns a result JSON conforming to `RESULT_SCHEMA`:

```json
{
  "schema": "claude-obsidian.transaction-result.v1",
  "operation_id": "my-update-001",
  "status": "applied",
  "bundle_sha256": "<hash of the applied bundle>",
  "runtime": { "duration_ms": 123 }
}

```

Simultaneously, the system writes a journal entry following `JOURNAL_SCHEMA` to `.vault-meta/transactions/<operation_id>/journal.json`. This persistent log records pre-condition hashes, write outcomes, and timestamps, enabling the rollback logic implemented in `_confined_vault_unlink` and `_confined_vault_write`.

## Security and Validation: The Approval Hash

Before execution, the system computes an **approval hash** using `plan_approval_sha256` (lines 287–309). This cryptographic binding incorporates:

- The bundle's canonical JSON representation
- The vault identity
- A projection of prepared writes

This hash ensures that any later inspection can verify the exact content that was approved, preventing tampering between review and execution.

## Working with the Schema in Python

The following example demonstrates constructing a valid transaction bundle and computing its approval hash:

```python
from pathlib import Path
from claude_obsidian.transaction import (
    safe_operation_id,
    plan_approval_sha256,
    BUNDLE_SCHEMA,
)

# 1️⃣ Build a write description

write = {
    "path": "wiki/notes/example.md",
    "mode": 0o644,
    "content_sha256": "c1e5b9…",   # pre‑computed SHA‑256 of new file bytes

    "original_sha256": None,       # file does not exist yet

}

# 2️⃣ Assemble the bundle

bundle = {
    "schema": BUNDLE_SCHEMA,
    "operation_id": safe_operation_id("my-update-001"),
    "operation_type": "save",
    "writes": [write],
    "backups": [],   # optional

}

# 3️⃣ Compute the approval hash (what a reviewer would sign)

vault_root = Path("/path/to/vault")
approval_hash = plan_approval_sha256(
    vault_root=vault_root,
    expanded_bundle=bundle,
    prepared_writes=[],   # normally filled after a planning step

)

print("Approve this transaction with hash:", approval_hash)

```

Apply the bundle via the CLI:

```bash
claude-obsidian transaction apply --vault /path/to/vault bundle.json

```

## Summary

- **Three distinct schemas** govern Claude-Obsidian transactions: `BUNDLE_SCHEMA` for input, `RESULT_SCHEMA` for output, and `JOURNAL_SCHEMA` for persistence.
- **Strict validation** occurs through `safe_operation_id`, `_normalize_vault_path`, and `_assert_portable_write_path` in [`claude_obsidian/transaction.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py).
- **Approval hashing** via `plan_approval_sha256` cryptographically binds the bundle to vault identity and write projections.
- **Journal files** live under `.vault-meta/transactions/<operation_id>/journal.json`, enabling deterministic recovery and audit trails.

## Frequently Asked Questions

### What is the exact schema version string for a transaction bundle?

The `BUNDLE_SCHEMA` constant resolves to `"claude-obsidian.transaction.v1"`. This string must appear in the `schema` field of any bundle submitted to the system, as defined at line 41 of [`claude_obsidian/transaction.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py).

### Where does Claude-Obsidian store transaction journals?

Journal entries persist under `.vault-meta/transactions/<operation_id>/journal.json` within the vault root. These files follow `JOURNAL_SCHEMA` and record write operations, pre-condition hashes, and timestamps to support rollback and recovery operations.

### How does the system validate file paths in a transaction bundle?

Path validation occurs through the helper functions `_normalize_vault_path` and `_assert_portable_write_path` (lines 54–104 in [`claude_obsidian/transaction.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py)). These ensure paths remain within the vault directory and adhere to cross-platform portability constraints.

### What operation types are valid for the `operation_type` field?

The `operation_type` must be one of the values defined in `OPERATION_TYPES`, which includes `"save"`, `"ingest"`, and `"autoresearch"`. The `safe_operation_id` function validates the operation ID format at lines 35–51, while the operation type itself is checked against the permitted enumeration at lines 44–58.