Releases: josortmel/EcoDB
v1.3.1 — Progressive zoom, fractal search, week rollups
v1.3 made the fractal memory reachable; v1.3.1 makes it economical and unified. An agent now boots its entire memory in ONE call: compressed narrative for the distant past, full granularity only for the open edge.
Added — Progressive zoom & fractal navigation
GET /api/v1/clusters/telescopic/progressive— progressive-zoom boot view. Each temporal layer is the compression of the previous one; closed periods are never re-read: yearly → unabsorbed quarterlies → unabsorbed monthlies → loose weeks →recent_days(only memories not inside any closed week). Per-level caps count distinct periods,sectionsparameter for size-capped clients.POST /api/v1/clusters/zoom— fractal drill-down. Enter at the highest abstraction, zoom by id: quarter → months → week → themes → raw memories. Optionalquery_textranks children semantically within each scope. Ownership-scoped end to end.- Week rollups — the consolidation cell weaves each closed week's thematic clusters into ONE unified weekly narrative (editable
CellAgent Week Rolluptemplate), with the thematic clusters preserved beneath assource_ids. Views read by lineage; monthly consolidation consumes rollups. Backfill is automatic on re-trigger; a rollup failure never sinks a successful thematic consolidation. - 2 new MCP tools (38 → 40):
get_progressive_view,fractal_search. Both declareanthropic/maxResultSizeChars, so a full boot arrives in one call on Claude Code without any client-side configuration.
Changed — Higher-consolidation prompts v2
Reasoning models undershoot global word targets badly in JSON output (a quarterly came out at 1/3 of its floor). v2 prompts add a mandatory reading protocol (every source represented or the result is invalid), per-section word budgets, and hard absolute minimums framed as execution failure. Measured on real data: monthly 1413/1200/1510 → 1656/1949/1582 words; quarterly 1250 → 3189. CELL_LLM_MAX_TOKENS env (default 32768).
Fixed
- Scheduled foresight extraction always failed when signals were found —
$4::textcast with a float param (asyncpgDataError); nowfloat8, consistent with existing metadata. - Deleted clusters silently blocked regeneration — idempotency only checked
cell_runs, so a ghost run could hide a whole month from a quarterly. Higher-consolidation idempotency now requires the active cluster to exist. - Overlapping weekly clusters — manual trigger, cron and catch-up cut weeks three different ways (rolling vs calendar windows). All paths now anchor to the last complete Mon..Sun week; weekly cron moved Sunday → Monday.
ecodb-cellpermanently "unhealthy" — inherited an HTTP healthcheck from the api image while serving no HTTP; disabled (the worker is PID 1, process state is the liveness signal).- Empty error strings on failed cell runs — the exception type name is preserved when the message is empty.
Image tags: ecodb-api 0.25.0, ecodb-mcp 1.8.0. Schema unchanged (5.3.0); migration 5.3.1_higher_prompts_v2 reseeds prompts idempotently.
v1.3.0 — Memory Agent
Memory Agent -- configurable cells, cluster access, provider keys
The metacognition engine (v2.0) produced clusters, narratives, foresights and skills, but nothing could read or configure them. v1.3 closes that loop.
Highlights
- Configurable cells -- model, provider, prompt template and cron schedule per agent, editable live from the dashboard without container restarts
- 3 level-adapted consolidation prompts -- monthly (1500-2000 words), quarterly (2500-4000), yearly (4000-6000), each with distinct narrative nature
- Cluster access -- semantic search over fractal memory (cosine + BM25, ownership-scoped), telescopic boot view (oldest-first: yearly to quarterly to monthly to weekly to last 3 days)
- LLM provider keys -- encrypted at rest (Fernet), managed from dashboard, multi-provider model router (DeepSeek + Anthropic)
- Generic cell handler -- define custom agentic task types beyond the 3 built-in cells
- 6 new MCP tools (32 to 38) + ecodb-langchain SDK 0.2.0 (9 to 13 native tools)
- Dashboard Memory Agent -- standalone page with Briefing, Configs, Clusters, Telemetry, Foresights, Skills tabs + live SSE + template editor
- Security hardening -- safe template formatter (blocks attribute traversal), ENCRYPTION_KEY validation, cell_type/provider regex, cluster source scoping
Schema
5.2.0 to 5.3.0 -- migration is idempotent, runs automatically on API startup.
Cell model
Default cell model is now deepseek-v4-pro (reasoning). No LLM timeout by default -- recover_stuck_runs (60 min) is the safety net.
Install
Existing installs: docker compose up --build -d -- migrations apply automatically.
Fresh installs: ./scripts/setup.sh now generates ENCRYPTION_KEY (required for provider key encryption).
Full changelog in CHANGELOG.md.
v1.2.5 — Metacognition v2.0
EcoDB v1.2.5 — Metacognition v2.0
EcoDB now thinks about its own memories. Schema 5.2.0. 22 new endpoints, 3 cell workers, identity evolution, authorship frontier. 30+ adversarial findings resolved.
Fresh install: git clone + setup.sh + docker compose up --build -d
Upgrade: git pull + docker compose build api + docker compose up -d api (migrations auto-apply)
Full changelog: CHANGELOG.md
v1.2.0 — Installation Path Consolidation
EcoDB v1.2.0 — Installation Path Consolidation
Fresh installs now work out of the box. Upgrades from any prior version are automatic.
What's new
Migration runner
Idempotent SQL migration runner (api/migrations.py) applies pending migrations on every API startup. Uses pg_advisory_lock to serialize concurrent startups. If a migration fails, the API refuses to start — a broken schema never silently serves traffic.
Fresh installs go from init.sql (5.0.0) to 5.1.1 automatically. Upgrades re-apply idempotent migrations (no-op on up-to-date schemas). No manual SQL needed.
Docker entrypoint with gosu
New entrypoint fixes media volume permissions automatically at container start. No more manual docker exec -u root chown after deploy.
INTERNAL_BROADCAST_SECRET hardened
- Hardcoded default removed from
docker-compose.yml(was publicly visible in repo) - Setup scripts now auto-generate a unique secret per installation (CSPRNG)
- Production startup warns if secret is missing or too short
Existing installs: if you never set
INTERNAL_BROADCAST_SECRETin.env, you were using the public default. Rotate it:openssl rand -hex 32and add to.env. See CLAUDE.md for details.
Dashboard error sanitization
Server errors (5xx) now show "Server error (500). Check server logs for details." instead of the misleading "Couldn't reach EcoDB" message.
Schema version test
New integration test (test_schema_version_matches_db) catches drift between settings.SCHEMA_VERSION and the actual database. Auto-skips if postgres is unavailable.
Version drift cleanup
Stale version references cleaned across settings, MCP, dashboard, and docs. CORS default corrected (8081 → 8091). ENVIRONMENT default changed to "development" for better local DX.
Documentation
- README: environment variables table, schema verification command, upgrade notes
- CHANGELOG: entries for v0.9.5 through v1.2.0
- CLAUDE.md: migration convention, broadcast secret rotation guide
Upgrade from v1.1.x
git pull
docker compose up --build -d
# Rotate broadcast secret if you never set it
openssl rand -hex 32
# Add INTERNAL_BROADCAST_SECRET=<value> to .env
docker compose restart api workerStats
- 22 files changed, 1018 insertions, 27 deletions
- 7 build tasks, 2 adversarial security loops, 2 verification loops
- Design: Prima (workflow-diseno v4, 2 design adversarial loops, 41 observations)
- Build: Hilo (orchestrator) + code (executor) + adv-code + adv-seg + verificador
v1.1.1 — Fresh-install fixes
Patch release fixing a clean-setup failure reported by an external user.
Fixed
- Fresh install now reaches schema 5.1.1. A clean
docker compose uponly raninit.sql(frozen at schema 5.0.0); the incremental migrations were never applied, so tool calls returned 500s (memory_embeddings,nodes.name_canonical,api_keys.grace_untilmissing) and the knowledge graph broke silently (missing AGE sync triggers). The migrations and triggers are now mounted indocker-entrypoint-initdb.dand applied automatically on first boot. Existing installs are unaffected —initdb.donly runs on an empty data volume. - API key bootstrap works without arguments.
bootstrap_first_apikey.pyauto-detects the super user;--user-id/--nameare now optional.
Added
scripts/setup.ps1— Windows PowerShell setup, equivalent tosetup.sh.
Docs
- README roadmap visual refreshed (v0.9 done, v1.0 dashboard current).
Notes
- No dashboard/installer change — the v1.1.0 desktop installer remains current.
- Installs predating this fix may need
sql/migrate_5.1.0_to_5.1.1.sqlandsql/trigger_age_sync.sqlapplied manually. An automatic migration runner (covering upgrades, not just fresh installs) is planned.
EcoDB v1.1.0 — Dashboard alias control
EcoDB v1.1.0 — Dashboard alias control
The desktop dashboard gains manual control over entity-alias governance.
Dashboard
- Alias scan: retroactive discovery of alias candidates across active nodes — similarity threshold slider (pg_trgm), max-per-name, optional name filter, and a dry-run preview that shows what would be persisted without touching the DB.
- Merge direction: choose which node survives a merge. Default collapses source into target; invert it so the source survives instead. The node being absorbed is flagged in red.
Backend
- Alias pipeline fix: automatic detection now fires on memory creation.
POST /admin/alias-candidates/scan(threshold, max_per_name, name_filter, dry_run) — additive, no duplicates.reverseflag on alias-candidate review.
Install
Windows installer attached (unsigned — SmartScreen will warn on first run).
v1.0.0 — EcoDB Desktop Dashboard
EcoDB v1.0.0 — Desktop Dashboard
EcoDB ships its first desktop interface. The engine had 32 MCP tools, a 10-stage GAMR pipeline, multi-tenant isolation, and LoCoMo R@5=0.922. Now it has a face.
Dashboard (Electron) — built by Lienzo:
- Command Center: stats cards, activity feed (SSE), attention inbox with 4 decision classes
- Knowledge Explorer: GAMR search with score breakdown, memory browser, staleness management
- Graph Studio: full knowledge graph visualization with Louvain clusters and degree-based layout
- Settings: trust tiers, entity dictionary, predicates CRUD, API key management
- Cmd+K launcher, offline degradation with cached data, first-run diagnostics
Backend delivered alongside dashboard:
- GET /graph/all — full graph paginated (degree DESC, cluster_id)
- POST/PUT/DELETE /admin/predicates — canonical predicate management
- POST /admin/merge-entities — keep_as_alias flag
- POST /documents/upload — multipart file upload for ingestion
- GET /admin/attention-inbox/summary + /details — org-scoped governance inbox
Infrastructure — shared between API and worker:
- Shared Docker media volume for uploads
- INTERNAL_BROADCAST_SECRET wired for SSE document lifecycle events
- Multi-tenant org scoping (v0.9.5): SSE events, rate limiting, Louvain SQL pre-filtering, search warnings
Stats: 1414 nodes, 3293 triples, 1398 active nodes, 32 MCP tools, 6 Docker containers, 10 GAMR stages.
Built by Pepe (product), Prima (architecture), Hilo (backend), and Lienzo (frontend). Three days of continuous coordination. June 2026.
v0.9.5 — Debt Resolution & Dashboard Backend
EcoDB v0.9.5 — Debt Resolution
Zero-debt release. All architectural debt from v0.9.0 resolved. Dashboard backend complete.
SSE org-scoped broadcast
Events now carry org_id. Non-super clients only receive their organization's events. Worker document lifecycle events (document_indexed, document_failed, duplicate_detected) now send correctly with X-Internal-Secret auth and org_id resolution.
Method-aware rate limiting
POST /memories/preview = 10/min, POST /memories = 20/min. GET paths unchanged at 120/min. Rate limit key now includes HTTP method — different methods on the same path don't share buckets.
Louvain optimization
SQL pre-filtering via JOIN instead of Python set filtering. Configurable LOUVAIN_MIN_DEGREE env var. Empty result guard prevents accidental cluster data wipe.
Search improvements
user_id filter now correctly excludes document chunks (documents have no individual author). New warnings field in SearchResponse for machine-parseable query behavior notices.
10 mechanical fixes
- TeamResourceLink model with actual fields
- Node name case-insensitive lookup (trigram suggestion)
- Graph clusters pagination (limit/offset)
- AGE statement_timeout 4.5s on Cypher queries
- Onboarding contradictions = None stub
- graph_clusters cleanup on entity merge
- SSE event_type newline sanitization
- Clusters offset cap (50k)
- Dead code removal
- Rate limit key eviction for inactive users
Documentation
docs/design/graph-org-scoping.md— shared graph + visibility layer directiondocs/migration-v0.9-to-v0.9.5.md— migration guide with DD8 trigger behaviordocs/DASHBOARD_BACKEND_GUIDE.md— complete backend integration guide for frontend- 4 new trigger verification tests
- Schema v5.1.1 (graph_clusters table)
2 adversarial design loops (Prima) + 2 construction loops (adv-code + adv-seg + verificador + code). All findings resolved.
v0.9.0 — Multi-tenant
EcoDB v0.9.0 — Multi-tenant
EcoDB goes multi-tenant. Organization isolation across all endpoints, API key rotation with zero-downtime grace periods, CEO-level admin operations, and audit trail on every mutation.
Highlights
Organization isolation — Every JWT now carries organization_id for all roles (Workers, Leads, CEOs). Search, memory access, admin operations, and API key management are all scoped to the user's organization. Super users retain platform-wide access.
API key rotation — POST /auth/api-keys/{key_id}/rotate issues a replacement key while the old key stays valid during a configurable grace period (1-720 hours). Both keys work simultaneously. No client coordination needed. Max 3 active keys per user with automatic cleanup.
CEO admin access — 7 admin endpoints now accessible to organization CEOs (was super-only): alias candidate review, entity merge/undo, document trust tiers, related document confirmation, and graph vocabulary. All operations are org-scoped with fail-closed permission checks.
Graph discovery pre-filter — Search graph discovery now filters by visible_project_ids before truncation, preventing cross-org memory leakage through graph traversal paths.
Complete audit trail — ~40 audit_log calls across 14 files. Every mutation endpoint writes an audit record with organization_id. Covers memories, projects, teams, workspaces, agents, auth, documents, events, graph, and admin operations.
Rate limiting hardened — JWT signature now verified in rate limiter (prevents bucket spoofing). Retry-After and X-RateLimit-* headers on all responses.
Schema migration
Schema v5.0.1 → v5.1.0. Migration is idempotent with rollback script included.
# Apply migration
docker exec -i ecodb-postgres psql -U ecodb -d ecodb < sql/migrate_5.0.1_to_5.1.0.sql
# Rebuild containers
docker compose up --build -dNew columns: users.organization_id, api_keys.replaced_by_key_id, api_keys.grace_until, teams.organization_id, audit_log.organization_id. 4 new triggers for org propagation and team cross-org constraints.
Full migration guide: docs/migration-v0.8-to-v0.9.md
Claude Desktop support
MCP server now accepts --transport stdio as a CLI argument, fixing the port conflict when Claude Desktop launches the MCP via docker exec. See updated README for configuration.
Security
3 adversarial review loops (code quality + security). ~35 findings identified and resolved:
- Cross-org data leakage in admin endpoints → org-scoped queries
- IDOR oracles (404 vs 403) → unified 404 responses
- API key rotation chain corruption → serialized with
SELECT FOR UPDATE - Rate limit bucket spoofing → JWT signature verification
- Grace-period zombie keys → auto-deactivation on failed auth
What's next
- v1.0 Dashboard — React+Vite+Tailwind frontend (Spec+Plan ready)
- Installation experience — simplified setup for new users
- Graph isolation — per-org graph partitioning (deferred to first customer with sensitive data)
v0.8.6 — Security hardening + infrastructure consolidation
Security
- Graph discovery permission bypass (
search.pyGC1):check_visibility()now applied when fetching graph-discovered memories — workspace scoping, CEO status, and lead permissions were previously bypassed - MCP server crash on validate_link:
validate_linktool now wrapped in try/except; unhandledRuntimeErrorpreviously crashed the entire MCP server - IDOR oracle fixes (
memories.py):delete_memory,unarchive_memory, andvalidate_linknow return uniform 403 for both missing and unauthorized access — prevents existence enumeration - Path traversal in MCP tools: UUID format validated before use in all memory and document tools;
quote()usessafe=''to encode all special characters
Infrastructure
- MCP media volume: mounted with write access for
save_memory(image_path=...)support - MCP startup without API key: empty default allows first boot before key generation
- Backup/restore container name: default corrected to
ecodb-postgres - NER Dockerfile: versions pinned (
fastapi==0.118.0,uvicorn==0.40.0,gliner==0.2.26), dedicated group GID 1001 - MCP dependency cap:
mcp[cli]>=1.0.0,<2.0.0
Robustness
- search() input validation:
limit(1–100) anddeep_factor(1–10) validated at MCP layer - search_recent() tag param: corrected
tag→tagsto match API contract - AGE hop retry: hop=2 still attempted if hop=1 fails
- AGE node creation race guard: defense-in-depth try/except on
_age_create - Worker stuck document recovery:
recover_stuck_documents()at startup resets or fails documents stuck after process crash
Documentation
- MCP tool count: 22+ → 32
- stdio transport config example added
- Spanish runtime error strings translated to English
- Stale container name references cleaned up
16 files changed, +394/-46 lines. 10 original tasks + 12 adversarial fixes. 2 full review loops. 300/304 tests pass (3 pre-existing). 0 regressions.