---
version: 0.9.1
feature_pitch:
  headline: "Security hardening + 30x faster embeddings"
  description: "4 security fixes (search DoS, slug hijack, symlink traversal, content bombs), PGLite crash fix, 12 data integrity fixes, 30x embed speedup, and search pagination. Community fix wave: 10 PRs, 7 contributors."
  recipe: null
  tiers: null
---

# v0.9.1 Migration: Security + Integrity + Performance

This migration includes security hardening, data integrity fixes, and a
performance improvement that changes how hashes are computed. Existing users
will see a one-time full re-import on next sync.

## What Changed

### Content hash algorithm
The content hash now includes all page fields (title, type, frontmatter), not
just compiled_truth + timeline. This means every existing page's hash will differ
on next sync, triggering a full re-import. This is expected and correct.

### Slug authority (BREAKING for some brains)
The file path is now the source of truth for slugs. If a markdown file has a
frontmatter `slug:` field that disagrees with its path, the import is REJECTED
(skipped with an error). This prevents page-hijack attacks in shared brains.

**If your brain uses frontmatter `slug:` overrides intentionally**, those pages
will be skipped on next sync. Fix by either:
- Removing the `slug:` line from frontmatter (let the path determine the slug)
- Moving the file to match the declared slug

Run `gbrain sync` and check for "Skipped ... does not match path-derived slug"
errors. Fix any before proceeding.

### Search limit ceiling
Search results are now capped at 100. If your agent requests more, it gets a
warning and 100 results. Use the new `--offset` flag to paginate.

### Embedding performance
`gbrain embed --all` now runs 30x faster (sliding worker pool, 20 concurrent
by default). A 20,000-chunk corpus that took 2.5 hours now takes ~8 minutes.

## Agent Instructions

### Step 1: Run sync (expect full re-import)

The content hash change will cause all pages to re-import. This is expected.

```bash
gbrain sync
```

You will see all pages reported as "imported" instead of the usual few "modified".
This is a one-time event.

### Step 2: Re-embed all pages

After the re-import, embeddings need refreshing:

```bash
gbrain embed --all
```

With the new parallel worker pool, this should complete in under 10 minutes
for most brains. Set `GBRAIN_EMBED_CONCURRENCY=10` if you hit API rate limits.

### Step 3: Verify search works

```bash
gbrain search "test query" --limit 5
```

If search returns results, the re-import and re-embed worked correctly.

### Step 4: Done

```bash
mkdir -p ~/.gbrain/migrations
echo '{"version":"0.9.1","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","status":"complete"}' >> ~/.gbrain/migrations/completed.jsonl
```
