feat: v0.9.0 -- smart file storage, publish, production-grade skills (#62)
* feat: battle-tested skill patterns from production deployment Backport production-learned brain-operations patterns: - Iron Law of Back-Linking (mandatory bidirectional linking) - Brain filing rules (file by primary subject, not format) - Enrichment protocol (7-step pipeline, 3-tier system, person/company templates) - Media ingest workflows (articles, videos, podcasts, PDFs, screenshots) - Citation requirements (mandatory [Source: ...] on every fact) - Test Before Bulk operating principle - Voice recipe: unicode crash fix, PII scrub, identity-first prompt, DIY STT+LLM+TTS - X-to-Brain recipe: image OCR, Filtered Stream, tweet rating rubric, cron stagger * chore: bump version and changelog (v0.8.1) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add _brain-filing-rules.md to CLAUDE.md key files * feat: smart file upload with TUS resumable and .redirect.yaml pointers - Supabase Storage auto-selects upload method by file size: < 100 MB standard POST, >= 100 MB TUS resumable (6 MB chunks + retry) - Signed URL generation for private bucket access (1-hour expiry) - New `upload-raw` command with size routing: small text stays in git, large/media files go to cloud with .redirect.yaml pointer - New `signed-url` command for generating access links - File resolver supports both .redirect.yaml (v0.9+) and .redirect (legacy) - Redirect format upgraded: 10 fields with full metadata - All migration commands (mirror, redirect, restore, clean) handle both formats * feat: skills reference actual gbrain file commands - Filing rules document upload-raw, signed-url, and .redirect.yaml format - Ingest skill uses gbrain files upload-raw for raw source preservation - Maintain skill adds file storage health checks - Setup skill adds storage configuration phase with migration guidance - Voice recipe uses upload-raw for call audio storage - Migration v0.9.0 with complete storage setup instructions * chore: bump version and changelog (v0.9.0) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: gbrain publish -- shareable HTML with password protection First code+skill pair: deterministic code does the work (strip private data, encrypt with AES-256-GCM, generate self-contained HTML), the skill tells the agent when and how to use it. 34 new tests. See: https://x.com/garrytan/status/2042925773300908103 * feat: backlinks check/fix, page lint, and report commands Three new deterministic tools (zero LLM calls): - gbrain backlinks check/fix -- scans brain for entity mentions without back-links, creates them. Enforces the Iron Law from the skills. - gbrain lint [--fix] -- catches LLM preambles, code fence wrapping, placeholder dates, missing frontmatter, broken citations, empty sections. --fix auto-strips fixable artifacts. - gbrain report --type <name> -- saves timestamped reports to brain/reports/{type}/YYYY-MM-DD-HHMM.md for audit trails. 33 new tests (409 total, 0 fail). * feat: v0.9.0 migration tells agents to swap scripts for built-in commands Migration file now: - Lists all 5 new deterministic commands with usage examples - Includes a script-to-command replacement table (old -> new) - Tells the agent to find custom script references in AGENTS.md, skills, and cron jobs and replace with gbrain commands - Adds recommended cron jobs for daily backlink fix + weekly lint - References the Thin Harness, Fat Skills thread * fix: CLI routing bugs found during DX review - Fixed subArgs reference error in handleCliOnly (used wrong variable name) - Renamed gbrain backlinks check/fix to gbrain check-backlinks to avoid conflict with existing backlinks operation (per-page incoming links) - Added TOOLS section to --help output showing publish, check-backlinks, lint, report - Added upload-raw and signed-url to FILES section in --help - Updated all docs/migration references to use check-backlinks * fix: security hardening from adversarial review - XSS: sanitize marked.parse() output (strip script/iframe/on* attrs) - Path traversal: validate report --type against [a-z0-9-] pattern - TUS: HEAD request before retry to get server's actual offset (TUS spec) - Pointer: upload-raw now includes pointer content in JSON output - Symlinks: use lstatSync in all walkers to prevent directory escape --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
129
skills/publish/SKILL.md
Normal file
129
skills/publish/SKILL.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Publish Skill
|
||||
|
||||
Share brain pages as beautiful, self-contained HTML documents. Optionally
|
||||
password-protected with client-side AES-256-GCM encryption. No server needed.
|
||||
|
||||
This is a **code + skill pair**: the deterministic code (`gbrain publish`) does
|
||||
the stripping, encrypting, and HTML generation. This skill tells you when and
|
||||
how to use it. See [Thin Harness, Fat Skills](https://x.com/garrytan/status/2042925773300908103)
|
||||
for the architecture philosophy.
|
||||
|
||||
## When to Publish
|
||||
|
||||
- User asks to share a brain page, create a shareable link, or says "give me a page"
|
||||
- User wants to send a deal memo, person briefing, or research to someone external
|
||||
- User asks to publish a data room analysis or trip plan
|
||||
- Any time brain content needs to leave the brain without exposing the whole system
|
||||
|
||||
## Default: ALWAYS ENCRYPT
|
||||
|
||||
Brain content is private. Default to password-protected unless the user explicitly
|
||||
says "open", "no password", or "public".
|
||||
|
||||
If no password is specified, auto-generate one. Share the password via a different
|
||||
channel than the URL.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```bash
|
||||
# Basic publish (outputs local HTML file)
|
||||
gbrain publish brain/companies/acme.md
|
||||
|
||||
# Password protected (auto-generate password)
|
||||
gbrain publish brain/companies/acme.md --password
|
||||
|
||||
# Password protected (specific password)
|
||||
gbrain publish brain/companies/acme.md --password "secret123"
|
||||
|
||||
# Custom title
|
||||
gbrain publish brain/companies/acme.md --password --title "Acme -- Deal Analysis"
|
||||
|
||||
# Custom output path
|
||||
gbrain publish brain/companies/acme.md --out /tmp/acme-share.html
|
||||
```
|
||||
|
||||
## What Gets Stripped
|
||||
|
||||
The publish command automatically removes all private/internal data:
|
||||
|
||||
| Stripped | Example | Why |
|
||||
|---------|---------|-----|
|
||||
| YAML frontmatter | `title:`, `type:`, `tags:` | Internal metadata |
|
||||
| `[Source: ...]` citations | All formats | Provenance is internal |
|
||||
| Confirmation numbers | `ABC123DEF` -> "on file" | PII/booking data |
|
||||
| Brain cross-links | `[Jane](../people/jane.md)` -> `Jane` | Internal paths |
|
||||
| Timeline section | Everything below `---` / `## Timeline` | Raw evidence log |
|
||||
| "See also" lines | Internal references | Brain navigation |
|
||||
|
||||
**Preserved:** external URLs (`https://...`), all other content.
|
||||
|
||||
## Sharing Workflows
|
||||
|
||||
### Option A: Local file (simplest)
|
||||
|
||||
```bash
|
||||
gbrain publish brain/people/jane-doe.md --password --out ~/Desktop/jane-briefing.html
|
||||
```
|
||||
|
||||
Share the HTML file via email, Slack, Airdrop. Share the password separately.
|
||||
|
||||
### Option B: Upload to cloud storage
|
||||
|
||||
```bash
|
||||
# Publish locally first
|
||||
gbrain publish brain/companies/acme.md --password "secret" --out /tmp/acme.html
|
||||
|
||||
# Upload to Supabase Storage
|
||||
gbrain files upload /tmp/acme.html --page shares/acme
|
||||
|
||||
# Get a signed URL (1-hour expiry)
|
||||
gbrain files signed-url shares/acme/acme.html
|
||||
```
|
||||
|
||||
Share the signed URL + password. URL expires in 1 hour. Re-generate as needed.
|
||||
|
||||
### Option C: Static hosting (Render, Netlify, S3)
|
||||
|
||||
Upload the HTML file to any static hosting service. The file is self-contained,
|
||||
no server logic needed. Password-protected files work entirely client-side via
|
||||
Web Crypto API.
|
||||
|
||||
### Option D: GitHub Pages / Gist
|
||||
|
||||
```bash
|
||||
gbrain publish brain/trips/japan-2026.md --out trip.html
|
||||
# Upload to a GitHub Gist or Pages repo
|
||||
```
|
||||
|
||||
## Password Protection Details
|
||||
|
||||
- **Algorithm:** AES-256-GCM
|
||||
- **Key derivation:** PBKDF2 with 100K iterations, SHA-256
|
||||
- **Salt:** Random 16 bytes per encryption
|
||||
- **IV:** Random 12 bytes per encryption
|
||||
- **Decryption:** Client-side via Web Crypto API (SubtleCrypto)
|
||||
- **No server auth needed** -- the HTML file is self-contained
|
||||
- **"Remember on this device"** -- saves password in localStorage
|
||||
|
||||
When encrypted, the published HTML contains ONLY ciphertext. The plaintext is
|
||||
not present anywhere in the file.
|
||||
|
||||
## Updating a Published Page
|
||||
|
||||
Re-run the publish command with the same output path:
|
||||
```bash
|
||||
gbrain publish brain/companies/acme.md --password "same-password" --out shares/acme.html
|
||||
```
|
||||
|
||||
Same file, same URL (if hosted), updated content.
|
||||
|
||||
## Revoking Access
|
||||
|
||||
Delete the file. If using signed URLs, the URL expires automatically (1 hour).
|
||||
If using static hosting, remove the file from the host.
|
||||
|
||||
## Tools Used
|
||||
|
||||
- `gbrain publish` -- deterministic HTML generation (no LLM calls)
|
||||
- `gbrain files upload` -- upload to cloud storage (optional)
|
||||
- `gbrain files signed-url` -- generate access links (optional)
|
||||
Reference in New Issue
Block a user