Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,13 @@ ENGRAPHIS_LOOP_INTERVAL=60
ENGRAPHIS_LOOP_TOP_K=20
# Decay half-life in days (Ebbinghaus). Higher = memories persist longer.
ENGRAPHIS_DECAY_HALFLIFE_DAYS=7

# ── License & Team mode (Pro) ───────────────────────────────────────────────
# Engraphis core is free forever. A signed license key unlocks Pro features
# (analytics dashboard, compliance export) and Team mode (multi-user Inspector).
# Get a key at https://engraphis.dev/pro, then either set it here or paste it
# in the Inspector's license dialog (persists to ~/.engraphis/license.key).
# ENGRAPHIS_LICENSE_KEY=ENGR1.xxxxx.yyyyy
# Team mode: per-user logins + roles (admin/member/viewer) on the Inspector.
# Requires a Team license; first visit creates the admin account.
# ENGRAPHIS_TEAM_MODE=1
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ build/
.pytest_cache/
.ruff_cache/
models_cache/
.secrets/
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ python -m eval.external --dataset locomo10.json --format locomo --offline --limi
# ── v2 Memory Inspector (product UI over MemoryService; same layer as the MCP server) ──
python -m scripts.inspector # http://127.0.0.1:8710 (auth: ENGRAPHIS_API_TOKEN)

# ── Onboarding (writes .env with an absolute DB path; doctor mode verifies install) ──
engraphis-init # or: python -m scripts.init
engraphis-init --check

# ── Commercial layer (docs/LAUNCH_PLAN.md; gates live ONLY in inspector/app.py) ──
python -m scripts.license_admin keygen # vendor keypair → .secrets/ (gitignored)
python -m scripts.license_admin issue --email a@b.co --plan team --seats 5 --days 365
ENGRAPHIS_LICENSE_KEY=ENGR1... # or ~/.engraphis/license.key; free tier = no key
ENGRAPHIS_TEAM_MODE=1 # multi-user Inspector (needs a 'team' license)

# ── Sleep-time consolidation (schedulable local job; also an MCP tool) ────────
python -m scripts.consolidate --db engraphis.db --workspace acme --dry-run

Expand Down
43 changes: 43 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,49 @@
All notable changes to Engraphis are documented here. Format loosely follows
[Keep a Changelog](https://keepachangelog.com/); versions use SemVer.

## [Unreleased] — commercial layer: license keys, Pro analytics/export, Team mode

### Added
- **Offline signed license keys** (`engraphis/licensing.py`): Ed25519-signed
`ENGR1.<payload>.<sig>` keys verified pure-stdlib (RFC 8032 implementation, tested against
the RFC's own vectors) — no phone-home, no license server, no new dependency. Vendor CLI:
`python -m scripts.license_admin keygen|issue|verify` (private key lives in gitignored
`.secrets/`). Free tier is the absence of a key, never an error; a bad/expired key degrades
to free with the reason surfaced in the UI.
- **Pro: Analytics dashboard** — `/api/analytics` + an Analytics tab in the Inspector:
weekly growth, retention distribution, decay forecast (what the consolidation sweep will
archive in 7/30 days), resolver action mix, most-connected entities. Data layer is a pure
tested function (`engraphis/analytics.py`); charts are dependency-free inline SVG.
- **Pro: Compliance export** — `/api/export` + an export button in the Audit tab: full
bi-temporal workspace dump (live + superseded memories, sessions, audit trail) as
downloadable JSON (`MemoryService.export_workspace`).
- **Team mode** (`ENGRAPHIS_TEAM_MODE=1` + a Team license): multi-user Inspector with
PBKDF2 logins, hashed session cookies (HttpOnly, SameSite=Strict), first-run admin setup,
seat limits from the signed key, and server-side roles — viewer (read) < member
(+ governance) < admin (+ consolidate/users/license/export). Bearer token still works as a
service account for scripts. Single-user setups are byte-for-byte unchanged.
- **Upgrade UX without nagging**: plan badge + license dialog (paste-to-activate via
`/api/license/activate`), locked-feature teasers rendered only where a locked feature was
explicitly opened, and a guided first-run empty state with a copyable MCP config snippet.
- Tests: 40+ new (RFC 8032 vectors, key tamper/expiry/seats, role matrix, login throttle,
402 gating, analytics math) — all offline, `importorskip`-guarded like the rest.

- **Per-user audit attribution**: in team mode, pin/forget/correct audit rows record the
signed-in user's email as the actor (service + engine already supported `actor`; the
Inspector now passes it) — the Team tier's audit trail answers *who*, not just what.
- **`engraphis-init`** — one command from `pip install` to a configured, agent-connected
setup: writes `.env` with an **absolute** DB path (the silent default previously landed in
the package directory — site-packages on pip installs), optional `--token`, prints exact
Claude Code / Cursor / Cline / Zed MCP snippets with the DB path pinned via `env`, and
`--check` is a doctor (install, extras, DB writability, license state).
- Inspector polish: relative timestamps in the audit trail (exact time on hover), `/`
focuses the active tab's search box, Dockerfile documents the Inspector port (8710).

### Docs
- `docs/LAUNCH_PLAN.md` — monetization architecture, tier table, payments plan (merchant of
record), UI/UX roadmap, launch checklist. `SECURITY.md` §6 documents the team-auth design.
- README: corrected the MCP tool count (17), added `engraphis-init` to the quickstart.

## [Unreleased] — v1 dashboard drill-down + polish pass

### Fixed
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ RUN useradd --create-home --uid 10001 engraphis && mkdir -p /data && chown -R en
USER engraphis
VOLUME ["/data"]
EXPOSE 8700
# Memory Inspector (product UI): run with `docker … engraphis-inspector` or a second service.
EXPOSE 8710

HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=3 \
CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8700/memory/health').status==200 else 1)"
Expand Down
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,38 @@ pip install -e ".[all]" # everything

---

## Free forever vs. Pro

The engine — recall, bi-temporal history, governance, code graph, MCP server, single-user
Inspector — is free and Apache-2.0, permanently. A license key (verified **offline**; no
phone-home, in keeping with local-first) unlocks the paid layer:

| | Free | Pro ($20/mo) | Team ($35/user/mo) |
|---|---|---|---|
| Memory engine + 17 MCP tools | ✓ | ✓ | ✓ |
| Memory Inspector (single-user) | ✓ | ✓ | ✓ |
| Analytics dashboard (growth, retention, decay forecast) | | ✓ | ✓ |
| Compliance export (full bi-temporal JSON dump) | | ✓ | ✓ |
| Multi-user Inspector: logins, roles, seat management | | | ✓ |
| Priority support | | ✓ | ✓ |

Paste your key into the Inspector's license dialog (the plan badge, top-left) or set
`ENGRAPHIS_LICENSE_KEY`. Get a key at <https://engraphis.dev/pro>.

---

## Quickstart A — MCP server (the headline)

Plug Engraphis into any MCP-capable agent. With Claude Code:

```bash
pip install -e ".[mcp]"
engraphis-init # writes .env (DB location) + prints the exact snippets
claude mcp add engraphis -- engraphis-mcp
```

`engraphis-init --check` is the doctor: verifies the install, extras, and DB writability.

For Cursor / Cline / Zed / Windsurf, add to your MCP config:

```json
Expand All @@ -81,7 +104,7 @@ For Cursor / Cline / Zed / Windsurf, add to your MCP config:
}
```

Your agent now has 15 tools:
Your agent now has 17 tools:

| Category | Tool | What it does |
|---|---|---|
Expand Down Expand Up @@ -240,7 +263,7 @@ engraphis/
│ ├── core/ # v2 engine — interfaces, store, recall, scoring, resolve, schema, ids
│ ├── backends/ # pluggable embedder / vector index / reranker / codegraph (offline fallbacks)
│ ├── service.py # validated MemoryService facade (no MCP dependency)
│ ├── mcp_server.py # MCP server — 15 tools (write/read/governance/code/session)
│ ├── mcp_server.py # MCP server — 17 tools (write/read/governance/code/session)
│ ├── config.py # env-driven settings
│ ├── app.py # REST server (FastAPI) + dashboard + auth middleware
│ ├── routes/ stores/ engines/ llm/ # REST server surface
Expand Down
6 changes: 5 additions & 1 deletion RELEASE_READINESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ MASTER_PLAN.md; full detail in `CHANGELOG.md`:
3. **Encryption-at-rest** and **built-in rate limiting** (today: rely on disk encryption + a
reverse proxy) — required for the regulated/Enterprise ICP.
4. **Per-token tenant authorization** if you sell multi-tenant; today, isolate by instance.
5. **An actual Pro-tier feature to sell.** The v1 dashboard had two real bugs fixed this pass
5. **An actual Pro-tier feature to sell.** *(RESOLVED 2026-07-03 — see
`docs/LAUNCH_PLAN.md` and `CHANGELOG.md`: offline signed license keys now gate three
shipped features — Pro analytics dashboard, compliance export, and multi-user Team mode
on the Inspector — with activation UX in the product. Remaining before charging: rotate
the dev vendor keypair, set the real purchase URL, wire a merchant of record.)* The v1 dashboard had two real bugs fixed this pass
(Knowledge Graph fragmentation, stored XSS) and is now correct, but "correct" isn't "worth
$20/mo" — it's still a single-user local dashboard with no hosting, login, or team sync. See
`docs/GO_TO_MARKET.md` §10 for the specific recommendation (hosted + multi-user version of
Expand Down
23 changes: 23 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,29 @@ repos you intend to index, the same way you'd scope any other local tool.
regex indexer on any import or parse failure, rather than failing the write path. Pin
versions and run `pip audit` in your environment.

## 6. Team mode & license keys (commercial layer)

Team mode (`ENGRAPHIS_TEAM_MODE=1` + a `team` license) replaces the single bearer token on
the Inspector's `/api/*` with per-user sessions:

- **Passwords**: PBKDF2-HMAC-SHA256, 600k iterations, per-user salt, ≥10 chars; verification
is constant-time (`hmac.compare_digest`) and unknown emails still burn one PBKDF2 (no
user-enumeration timing oracle). Login failures share one generic message.
- **Sessions**: 32-byte `secrets` tokens delivered as `HttpOnly; SameSite=Strict; Path=/`
cookies and stored **hashed** (SHA-256) with a 12h TTL — a leaked users DB yields no usable
cookies. Logout, user-disable, and demotion revoke server-side. CSRF posture: SameSite=Strict
+ JSON-only bodies + loopback-only CORS; if you expose the Inspector beyond loopback, put
TLS in front (the cookie does not set `Secure` on plain HTTP loopback).
- **Roles** are enforced in the HTTP layer on every request (viewer < member < admin); the UI
only hides what the server already refuses. The last active admin cannot be demoted or
disabled. A valid bearer token acts as an admin service account so automation keeps working.
- **Login throttle**: 5 failures / 15 min → 60 s lockout (in-process, matching the Inspector's
single-process posture).
- **License keys** are Ed25519-signed payloads verified offline against a pinned vendor public
key (`engraphis/licensing.py`); nothing phones home. Keys carry no secrets — they are
entitlements, and the private signing key must never live in the repo (gitignored
`.secrets/`, rotate before selling: `python -m scripts.license_admin keygen`).

## Known limitations (not yet mitigated)
- Rate limiting: an optional in-process per-IP limiter now ships (`ENGRAPHIS_RATE_LIMIT`,
`ENGRAPHIS_RATE_WINDOW`), off by default; still front multi-process/distributed deployments
Expand Down
2 changes: 1 addition & 1 deletion docs/GO_TO_MARKET.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ roadmap item, not a shipped, billable feature. What's actually true today:

- The **free core is genuinely strong**: hybrid recall, bi-temporal history (`why`/`timeline`),
self-maintaining facts (deterministic conflict resolution), governance (forget/pin/correct,
scope-checked), a code-symbol graph, and a 15-tool MCP server — all covered by 127 passing
scope-checked), a code-symbol graph, and a 17-tool MCP server — all covered by 127 passing
tests. That is a real, demonstrable advantage over "just a vector store," and it's free,
matching Letta's "self-hosted = all features" positioning from §5.
- The **v1 dashboard** (the closest thing to a "Memory Inspector UI" that exists) had two real
Expand Down
126 changes: 126 additions & 0 deletions docs/LAUNCH_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Engraphis — Launch Plan (v1.0 release + first paid tier)

_Date: 2026-07-03. Companion to `RELEASE_READINESS.md` (state audit) and
`docs/GO_TO_MARKET.md` (pricing research). This document is the execution plan: what ships,
in what order, and how the paid tier works technically and commercially._

## 1. Where we are

The free core is launch-ready (127 tests, offline gate green, 17 MCP tools, hardened write
path). What was missing for revenue — and what this pass adds — is the commercial layer:
there was no license mechanism, no paid feature, and no upgrade path in the product. See §3.

## 2. Monetization architecture (decided 2026-07-03)

**Model: open-core with offline signed license keys.** The core stays Apache-2.0 and fully
functional. Pro features ship in this repo but activate only with a valid key. Keys are
Ed25519-signed JSON payloads verified **offline** — no phone-home, no license server, which
keeps the local-first promise intact (a memory engine that phones home would undercut the
entire pitch).

- Key format: `ENGR1.<base64url payload>.<base64url signature>`; payload carries plan,
features, seats, expiry. Verified against the vendor public key pinned in
`engraphis/licensing.py`. Verification is pure stdlib (RFC 8032 Ed25519), so the
numpy-only core guarantee holds.
- Issue keys with `python -m scripts.license_admin issue --email … --plan team`. The signing
key lives in `.secrets/` (gitignored). **Rotate the committed dev public key before selling
a single license** (`license_admin keygen`), and keep the production private key in a
password manager, never on a dev box.
- Honesty note (Apache-2.0): a determined user can fork out the gate. That is the accepted
trade of the Sidekiq-style model — you sell convenience, updates, and support to the honest
majority. Do not escalate to obfuscation; it poisons trust and never works anyway.

### Tiers

| Tier | Price (target) | What's in it |
|------|----------------|--------------|
| Free | $0 forever | Whole engine: MCP server, recall/why/timeline, governance, code graph, single-user Inspector |
| Pro | $20/mo or $200/yr | Analytics dashboard, compliance export (full bi-temporal JSON dump), priority support |
| Team | $35/user/mo | Pro + multi-user Inspector: logins, roles (admin/member/viewer), seat-limited keys |

$20 anchors against Letta Pro ($20) and mem0 Starter ($19); see GO_TO_MARKET.md §10. Team
pricing is per-seat because the seat count is in the signed key.

### Payments & fulfillment (not yet built — next step after this pass)

Use a merchant-of-record (Polar.sh or Lemon Squeezy — handles VAT/sales tax, ~5% fee) rather
than raw Stripe at this stage. Flow: checkout → webhook → `license_admin issue` → key
emailed. Automate with a ~50-line serverless function when volume justifies it; issue keys
manually for the first customers (it's also a customer-discovery channel). Add the purchase
URL in the Inspector's license dialog once live.

## 3. What ships in this pass (implemented)

1. **`engraphis/licensing.py`** — key parsing/verification, feature registry, cached
`current_license()`; reads `ENGRAPHIS_LICENSE_KEY` or `~/.engraphis/license.key`.
2. **`scripts/license_admin.py`** — vendor CLI: `keygen`, `issue`, `verify`.
3. **Inspector license UX** — plan badge in the header, license dialog (activate key, see
features), tasteful locked-tab teasers. Free tier is never nagged mid-workflow; upsell
surfaces are opt-in clicks.
4. **Pro: Analytics tab** — memory growth, retention distribution, decay forecast (which
memories fall below the archive threshold in 7/30 days), resolver action mix, top
entities. Server-side in `engraphis/analytics.py` (numpy/stdlib only), inline-SVG charts
client-side (no chart library, consistent with the zero-dependency house style).
5. **Pro: compliance export** — one-click full workspace dump (memories incl. superseded
history, audit trail, sessions) as attachment-download JSON.
6. **Team: multi-user Inspector** — `ENGRAPHIS_TEAM_MODE=1` + a `team` key enables login
(PBKDF2, HttpOnly session cookie), first-run admin setup, roles enforced server-side
(viewer=read, member=+governance, admin=+consolidation/users/export), Team tab for user
management. Without team mode nothing changes for existing single-user setups.
7. **Tests** for all of the above, following the repo's `importorskip` CI-gate convention.

## 4. UI/UX improvements — beyond this pass

Ordered by effort-to-impact; the Inspector is already accessible (ARIA tabs, keyboard nav,
dark/light) so this is polish, not rescue:

1. **First-run experience**: when no workspaces exist, show a guided empty state with the
exact MCP config snippet to paste into Claude Code/Cursor (copy button), instead of a
toast. Biggest funnel fix available — the current first screen is blank.
2. **Onboarding command**: `engraphis init` that writes `.env`, picks a DB path, and prints
the MCP snippet. Closes the "install → configured agent" gap in one step.
3. Global search-as-you-type across tabs (debounced recall), keyboard palette (`/` to focus
search), relative timestamps ("3d ago") with exact time on hover.
4. Graph visualization of entity/link neighborhoods in the detail dialog (SVG, force layout
is overkill — radial layout is fine at this scale). Candidate second Pro feature.
5. Retire the v1 dashboard from the default install (`engraphis-server` keeps serving it for
compat, but docs point at the Inspector only) — one product surface, one story.

## 5. Feature roadmap (next / later)

**Next (pre-1.0):** encryption-at-rest for the SQLite file (SQLCipher optional extra →
`encryption` feature flag, regulated-ICP requirement per RELEASE_READINESS.md §"Before you
charge" #3); consolidation policies (saved schedules with per-scope thresholds) as a Pro
feature; publish LoCoMo/LongMemEval numbers (the eval adapter already exists).

**Later:** SSO/OIDC for Team (gate: first team customer asking); hosted Inspector (gate:
recurring demand — it abandons local-first, so it must be pull, not push); scale backends
(Qdrant/pgvector already behind interfaces); per-token tenant authorization for
multi-tenant hosting.

## 6. Launch checklist (ordered)

1. ~~License mechanism + first three paid features~~ (this pass).
2. Rotate vendor keypair; store private key offline. Set the real purchase URL in the
Inspector dialog and `licensing.py`.
3. Set up Polar/Lemon Squeezy product + webhook → key issuance.
4. `git commit` (the tree at HEAD must be the audited one), tag `v0.2.0`, push, verify CI
matrix (3.9/3.11), publish wheel to PyPI, smoke-test `pip install engraphis[all]` and the
Docker image.
5. Run LoCoMo benchmark, publish numbers in README (honest recall@k, per
RELEASE_READINESS.md #1).
6. Trademark search on "Engraphis" (#2 there) before spending on brand.
7. Launch free tier loudly (Show HN, MCP directories, r/LocalLLaMA — the local-first angle
is the hook), sell quietly (license dialog + pricing page). Revisit pricing after ten
real conversations.

## 7. Risks

- **Someone forks out the gate** — accepted (see §2); mitigation is velocity and support,
not DRM.
- **Team mode expands the attack surface** — mitigated: PBKDF2-HMAC-SHA256 (600k iters),
hashed session tokens, SameSite=Strict cookies, login backoff, server-side role checks on
every route; see SECURITY.md §6. Still run `/security-review` on any change touching it.
- **Paid features drift into the free core's value story** — the line is: *the engine
remembers for free; seeing, proving, and sharing what it remembers is paid.* Analytics,
export, and team are all on the right side of that line. Keep it that way.
Loading