Commit Graph

118 Commits

Author SHA1 Message Date
b5ba2ecadb Merge pull request '🐾 fix(api): workspace DELETE must not report success it didn't perform' (#11) from fix/workspace-delete-orphan-libraries into main
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 4m32s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m17s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m47s
Reviewed-on: #11
2026-08-07 17:19:17 +00:00
e10331dd44 🐾 fix(api): workspace DELETE must not report success it didn't perform
DELETE returned 204 for a library owned by another user, having deleted
nothing. The caller (Daedalus) recorded the workspace as cleaned up and
dropped its own row, while the Library survived holding its globally-unique
name — so that name could never be reused, and nothing anywhere recorded why.

An unowned library now returns 409 owner_conflict, reusing the code the create
path already emits for the same condition. Ownership stays opaque on GET (404
as before): the disclosure concern is about reads, and a delete that silently
does nothing is the worse failure.

A genuinely absent library still returns 204 — that idempotency is relied upon
and is correct.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 13:03:32 -04:00
b5fba26d4c Merge pull request '🐾 fix(api): cascade collection and item deletes too' (#10) from fix/collection-item-cascade into main
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 4m24s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m12s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m38s
Reviewed-on: #10
2026-08-03 17:13:46 +00:00
15a517e389 🐾 fix(api): cascade collection and item deletes too
Collection and Item DELETE — both the REST endpoints and the HTML
views — called bare .delete(), leaking each collection's Items and every
item's Chunks/Images/ImageEmbeddings. New delete_collection_cascade and
delete_item_cascade in the shared library_delete service now back all
four paths. No orphan-Concept GC in either (that invariant stays
library-delete-only, matching the existing supersede path); the ingest
supersede helper in tasks.py now delegates to delete_item_cascade
instead of duplicating its Cypher.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 13:12:25 -04:00
c040e6f3dd Merge pull request '🐾 fix(api): cascade plain library delete; case-insensitive name conflict' (#9) from fix/library-api-delete-and-name-case into main
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 4m30s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m16s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m46s
Reviewed-on: #9
2026-08-03 16:45:48 +00:00
f1639dbdec 🐾 fix(api): cascade plain library delete; case-insensitive name conflict
DELETE /library/api/libraries/{uid}/ called bare lib.delete(), orphaning
Collections/Items/Chunks/Images and skipping Concept GC — the only delete
path not using the shared cascade. It now delegates to
delete_library_cascade like the HTML and workspace delete paths.

Name-conflict checks on both create endpoints are now case-insensitive
via find_library_by_name_ci (parameterised Cypher toLower comparison —
not neomodel iexact, which embeds the value in a regex and breaks on
names like "C++ Notes"). The Neo4j unique index is case-sensitive, so
"amazon connect" previously coexisted silently with "Amazon Connect",
confusing every name-matching client (Spelunker matches names
case-insensitively). The 409 reports the existing spelling. The plain
create also gains a UniqueProperty catch for the pre-check/save race,
mirroring the workspace path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 12:41:55 -04:00
7237468e3c Merge pull request '🐾 fix(tasks): unsupported file types fail ingest terminally, no retries' (#8) from fix/unsupported-file-type-terminal into main
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 4m11s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m15s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m49s
Reviewed-on: #8
2026-08-03 16:28:58 +00:00
e1f128659e 🐾 fix(tasks): unsupported file types fail ingest terminally, no retries
Unsupported file types raised a bare ValueError from the parser, which
ingest_from_daedalus treated like any transient fault — ERROR logs and
pointless Celery retries for input that can never parse. A new
UnsupportedFileTypeError (ValueError subclass, so existing callers still
catch it) is classified in the task as a terminal client-data failure:
logged at WARNING, job marked failed with reason
"unsupported_file_type", never retried.

Recovered from uncommitted work predating PR #6 (which deliberately
excluded it); test fixes on top: IngestJob's pk is id not job_id, and
.run() needs push_request() since the task persists self.request.id
into the NOT NULL celery_task_id column.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 12:27:24 -04:00
acf829e5ca Merge pull request '🐾 feat(library): per-app managed_by replaces hardcoded Daedalus badge' (#7) from feature/managed-by into main
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 4m34s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m29s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m42s
Reviewed-on: #7
2026-08-03 01:55:16 +00:00
0a14cf00c5 🐾 feat(library): per-app managed_by replaces hardcoded Daedalus badge
Libraries created through the API are now stamped with the name of the
UserToken that created them (Library.managed_by), on both the workspace
and plain create endpoints; web-session creates stay null/unmanaged. The
idempotent workspace re-POST lazily backfills null managed_by, and a
one-off backfill_managed_by command labels pre-existing rows (workspace
inference: kairos-mail-* → Kairos, else Daedalus; Spelunker via ingest
job provenance).

UI badges and warnings now render "Managed by <app>" via
managed_by_display (inference fallback keeps legacy rows accurate before
backfill). The list scope filter becomes all/managed/unmanaged with the
old daedalus/global values aliased for bookmarks. The plain create
endpoint also gains an explicit 409 name_conflict (previously a raw
UniqueProperty 500) reporting the existing library's uid and manager.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 12:39:10 -04:00
9f5df20d2b Merge pull request '🐾 fix(parsers): rasterize SVG instead of failing ingest' (#6) from fix/svg-ingest-rasterize into main
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m16s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m10s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m56s
Reviewed-on: #6
2026-07-26 12:03:42 +00:00
224541a4ce 🐾 fix(parsers): rasterize SVG instead of failing ingest
"svg" was in both IMAGE_EXTENSIONS and PYMUPDF_EXTENSIONS, and the image
check ran first, so every SVG reached PIL.Image.open — which cannot decode
vector XML. Ingest raised UnidentifiedImageError, logged "Failed to read
image file_type=svg", and counted documents_parsed_total{status="error"}.
SVG ingest has never worked.

Rasterize to PNG instead, via PyMuPDF (already a dependency). This also
unblocks the vision stage downstream: it sends images to a vision LLM as a
data: URI, which cannot carry image/svg+xml either, so the description and
OCR fields were unreachable for SVG regardless of the parse fix.

Route SVG explicitly before both extension sets. Falling through to
PYMUPDF_EXTENSIONS would parse but not split, and a multi-page Write note
rendered as one document is either blank (no root width/height, so MuPDF
falls back to US-Letter and emits the top-left corner) or an illegible tall
strip (root sized across every stacked page). Splitting per write-page
element is correct for both formats, and since Write never rewrites
existing files both persist indefinitely.

svg_raster is a deliberate twin of daedalus's extraction/svg.py — the repos
share no common package, so the duplication is noted in both docstrings and
fixes belong in both.

lxml is a new dependency: recover=True is needed for the real files that
aren't well-formed XML, and stdlib ElementTree has no equivalent.
2026-07-26 07:41:20 -04:00
3ae5adebed Merge pull request '🐾 feat(library): add 'email' library type' (#4) from feat/email-library-type into main
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 4m27s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m27s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m30s
Reviewed-on: #4
2026-07-12 12:20:48 +00:00
9f20110f56 🐾 feat(library): add 'email' library type
Kairos is about to provision per-user app-managed (workspace) libraries for
synced mail, and none of the existing types fit correspondence. New entry in
LIBRARY_TYPE_DEFAULTS mirrors journal's entry-level chunking (one message ≈
one entry) with instructions tuned for email: correspondents, dates,
requests/commitments, and quoted-reply context. Registered in the Library
node choices and the API serializer choice list; forms and
load_library_types derive from the registry, and the compose init sidecar
re-runs the seeder on deploy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 08:03:28 -04:00
d6b541636a Merge pull request '🐾 feat(settings): register kairos-mail source bucket for ingest' (#3) from feat/kairos-mail-bucket into main
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 4m22s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m26s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m53s
Reviewed-on: #3
2026-07-12 11:50:53 +00:00
d01afd6203 🐾 feat(settings): register kairos-mail source bucket for ingest
Kairos is about to start announcing rendered mail documents to
POST /library/api/ingest/ with source="kairos-mail". Without a registry
entry, unknown sources fall back to the daedalus bucket and every worker
fetch fails — this adds the KAIROS_S3_* env vars (pattern-copy of the
spelunker block) and the SOURCE_S3_BUCKETS["kairos-mail"] entry, plumbed
through .env.example and the worker service in docker-compose.

Settings-only; no code changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 07:36:12 -04:00
840b9435a3 ci: remove branch and PR tags from docker metadata
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m25s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m34s
Drop type=ref tags for branch and PR events, keeping only SHA-based
and latest tags to simplify the image tagging scheme.
2026-06-25 08:14:56 -04:00
6120e9cd1f fix(mnemosyne): correct celery healthcheck command
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 4m14s
CVE Scan & Docker Build / build-and-push (push) Successful in 47s
The exec-form CMD has no shell, so $$HOSTNAME was never expanded,
causing "celery@$HOSTNAME" to match no node and every healthcheck to
fail. Remove the -d filter (one worker per container makes it
unnecessary) and add -t 8 to accommodate broker round-trip latency.
2026-06-19 11:39:38 -04:00
31a98b4f3a feat(library): add workspace scope filter to library list view
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m52s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m15s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m43s
Add a `scope` GET parameter to `library_list` allowing users to filter
libraries by all, global-only, or Daedalus workspace-only. Includes a
filter form in the template, an updated empty state message, and tests
covering each scope branch with mocked Neo4j dependencies.
2026-06-19 06:45:19 -04:00
3394726ca1 Merge branch 'main' of ssh://git.helu.ca:22022/r/mnemosyne
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 4m5s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m26s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m35s
2026-06-19 06:30:21 -04:00
03e3155bd6 fix(settings): load .env from repo root instead of project dir 2026-06-19 06:30:07 -04:00
929a3c8c3c fix(library): expose Delete control for Daedalus-managed libraries in UI
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m37s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m9s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m56s
The backend already allows admin delete of a workspace-scoped Library via
the shared delete_library_cascade (commit 142e967), and the confirm-delete
page carries the Daedalus caution. But the detail template was never updated
to match: the Delete button stayed hardcoded `disabled` for any library with
a workspace_id, and the banner said "Do not delete it manually." So the
working route was unreachable from the UI — admins still could not clear an
orphaned Library blocking workspace re-registration.

Make Delete an unconditional enabled link to library:library-delete (the
confirm page already warns), and rewrite the workspace banner to describe the
escape hatch (deleting here removes embedded content; Daedalus recreates and
re-embeds on the next sync) instead of forbidding it.

Template-only change; no view/model/migration changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 23:03:47 -04:00
2af72d6e82 ci: build only on push to main, not on pull_request
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m30s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m33s
Drop the pull_request:[main] trigger so the CVE scan + Docker build runs
only when changes land on main, not when a PR is opened against it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 06:14:52 -04:00
70b1fc510b Merge pull request 'fix(tests): repair stale mock.patch targets after service refactors' (#2) from fix/stale-test-patch-targets into main
Some checks failed
CVE Scan & Docker Build / security-scan (push) Has been cancelled
CVE Scan & Docker Build / build-and-push (push) Has been cancelled
Build & Deploy Docs / build-and-deploy (push) Successful in 1m11s
Reviewed-on: #2
2026-06-18 02:01:25 +00:00
46ca2a934d Merge pull request 'feat/workspace-name-conflict-409' (#1) from feat/workspace-name-conflict-409 into main
Some checks failed
CVE Scan & Docker Build / security-scan (push) Has been cancelled
CVE Scan & Docker Build / build-and-push (push) Has been cancelled
Build & Deploy Docs / build-and-deploy (push) Has been cancelled
Reviewed-on: #1
2026-06-18 02:00:55 +00:00
dd06f923cd feat(workspaces): return 409 name_conflict instead of 500 on Library name clash
Some checks failed
CVE Scan & Docker Build / security-scan (pull_request) Successful in 3m49s
CVE Scan & Docker Build / build-and-push (pull_request) Has been cancelled
A recreate of a workspace whose Mnemosyne Library was orphaned (left behind
by a failed Daedalus delete-propagate) collides on the global Library.name
unique constraint. neomodel raised UniqueProperty unguarded, so workspace_create
500'd and ingest then 404'd forever — the queue froze silently.

Guard lib.save() and return a structured 409 with a machine code so Daedalus
can classify the failure without string-matching:
- name_conflict   — the new name-collision case
- owner_conflict, library_type_immutable — codes added to the two existing 409s

Cypher-touching paths stay covered by the manual end-to-end plan, per the
test module's stated convention.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 20:26:43 -04:00
539d9b6c34 fix(tests): repair stale mock.patch targets after service refactors
All checks were successful
CVE Scan & Docker Build / security-scan (pull_request) Successful in 5m24s
CVE Scan & Docker Build / build-and-push (pull_request) Successful in 2m58s
Several library tests patched symbols at import paths that no longer
expose them, so they errored (AttributeError) instead of testing anything
— giving false confidence. The underlying code is correct; only the test
patch targets were stale after earlier refactors moved imports
function-local.

- test_pipeline: patch source modules (library.models.Item,
  llm_manager.models.LLMModel, library.services.parsers.DocumentParser,
  .chunker.ContentTypeChunker, .embedding_client.EmbeddingClient,
  .vision.VisionAnalyzer, .concepts.ConceptExtractor) since pipeline.py
  imports them inside methods. default_storage stays (still module-level).
- test_search_api: patch library.services.search.SearchService (the view
  imports it function-local).
- test_tasks: patch library.services.pipeline.EmbeddingPipeline (tasks.py
  imports it function-local).
- test_search_views_admin_scope: patch library.utils.neo4j_available; the
  guard moved to utils when views._all_library_uids became a thin alias.
- test_concepts: remove SampleIndexSelectionTests — _select_sample_indices
  was deleted in the document-level concept-extraction refactor (dead test).

Not addressed here: SearchAPIAuthTest / SearchAPIValidationTest return 302
instead of 401/400. Static analysis ruled out routing, middleware, and DRF
config; reproducing needs a running server (DB-backed). Flagged for sandbox
diagnosis — not a stale-patch issue.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 20:12:46 -04:00
142e9675b5 feat(library): allow admin delete of Daedalus-managed library via shared cascade
Admin/HTML library delete previously hard-blocked workspace-scoped
(Daedalus-managed) libraries, leaving no way to clear an orphaned Library
node — e.g. one left behind when a Daedalus workspace delete failed to
propagate. A recreate of that workspace then collides on the global
Library.name unique constraint and 500s, freezing ingest.

Allow the delete behind the existing confirm warning (low risk: source
content lives in Daedalus and is recreated + re-embedded on next sync),
and route both the API and HTML delete paths through one shared cascade.

- Add library/services/library_delete.delete_library_cascade(lib), keyed on
  Library uid so it covers global and workspace-scoped libraries. It removes
  Chunks, Images/ImageEmbeddings, Items, Collections, the Library, then GCs
  orphan-only Concepts (verbatim from the API view, re-keyed workspace_id->uid).
- workspace_detail_or_delete (API) now calls the shared helper.
- library_delete (HTML) no longer blocks workspace_id libraries; it calls the
  cascade instead of a bare lib.delete() (which leaked child nodes — also a
  latent bug for global libraries with content).
- Confirm-delete template shows a caution banner for Daedalus-managed libraries.

No migration: Mnemosyne library data is in Neo4j (neomodel); no schema change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 19:37:58 -04:00
a90c6e7479 feat(metrics): add scrape-time system model health collector
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m49s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m9s
CVE Scan & Docker Build / build-and-push (push) Successful in 3m32s
Add a Prometheus custom collector that probes the four system-default
models (chat, vision, embedding, reranker) at /metrics scrape time and
emits up/down, configured, and probe-latency gauges. This complements
the ingest-pipeline counters in the Celery worker, which only move
during active ingests and cannot signal model outages on an idle queue.

- New `library/health_collector.py` registers a custom collector with
  a 55s in-process cache to avoid hammering GPU endpoints on rapid
  scrapes or across multiple gunicorn workers.
- New `library/services/model_health.py` centralises the probe logic,
  resolving system-default models via SystemSettings and dispatching
  to chat/embedding/rerank endpoints with a short timeout.
- Register the collector only in the web process (gunicorn/runserver)
  via `LibraryConfig.ready`, excluding Celery, pytest, and management
  commands to prevent duplicate registration and stray probes.
- Add unit tests covering the collector cache, metric shape, and
  per-role probe dispatch.
2026-06-17 09:06:11 -04:00
4dde063299 fix(web): trust XFF for real client IP and correct port to 23081
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m41s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m9s
CVE Scan & Docker Build / build-and-push (push) Successful in 3m29s
- Configure nginx `set_real_ip_from` for RFC1918 ranges and enable
  `real_ip_recursive` so allowlists evaluate the true client IP
  instead of Docker's NAT gateway, preventing public exposure of
  `/metrics` and `/nginx_status`
- Update published port from 23181 to 23081 in docker-compose
2026-06-17 06:58:36 -04:00
ec4f12d601 feat(ingest): source-bucket registry keyed on ingest source
Generalises the Daedalus-only cross-bucket fetch into a registry
(SOURCE_S3_BUCKETS) keyed on the IngestJob `source` field, so new
upstream sources (Spelunker) can ingest from their own buckets. The
ingest task now calls fetch_from_source(job.source, job.s3_key) and
falls back to "daedalus" for blank/unknown sources (backwards compatible).

Adds SPELUNKER_S3_* env vars and worker env scoping. Replaces
daedalus_s3.py with source_s3.py.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 22:30:08 -04:00
75013ebfc3 refactor(concepts): document-level extraction with one chat call per item
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m20s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m8s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m49s
Concept extraction was making up to 10 LLM calls per item by sampling
chunks, which produced redundant work (the same concept reappears in
multiple chunks), context-loss bugs (chunk boundaries cut mid-thought),
and on a 35B model dominated per-item wall time (~3 min/item).

Concepts are document-level semantic objects; chunks are retrieval
units. Extract once per item from the first 100KB of parsed document
text, then connect each chunk to the concepts it explicitly mentions
via case-insensitive substring match — no extra LLM calls. Drops the
sample-indices selector that the old per-chunk loop relied on.

Stage 7 is currently dormant in production because the configured
chat model is a reasoning-mode Qwen variant that returns empty content
on every call (output stuck in reasoning_content). Re-enables cleanly
once a non-reasoning instruct model is set as is_system_chat_model.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 21:52:51 -04:00
bc80d90b38 fix(llm_manager): fail Test & Discover when openai base_url is missing /v1
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m20s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m7s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m35s
The OpenAI SDK used by _discover_openai_models tolerates a base_url
without /v1 (it auto-adds it for the probe), but every runtime client
(embedding_client, vision, concepts, reranker) treats base_url as the
/v1 root and appends path-only segments. A non-conforming base_url
silently passed Test & Discover and then 404'd at embed/chat/rerank
time.

Add _check_openai_v1_convention() which probes {base_url}/v1/models
when the URL doesn't end in /v1; on 200, fail the test with an
explicit "set base_url to .../v1 and re-test" message that points at
the exact bare-vs-/v1 mismatch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 21:21:26 -04:00
7d95133c74 chore(docker): close neomodel driver on gunicorn worker exit
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m9s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m38s
2026-05-23 19:51:25 -04:00
93639188d3 feat: rework auth model with UserToken and Daedalus/Pallas integration
Some checks failed
CVE Scan & Docker Build / build-and-push (push) Has been cancelled
CVE Scan & Docker Build / security-scan (push) Has been cancelled
Build & Deploy Docs / build-and-deploy (push) Successful in 1m10s
- Rename MCPToken to UserToken across models, views, and tests
- Update URL names from mcp-token-* to token-*
- Add Daedalus/Pallas integration design doc (v2)
- Switch docker-compose to build local mnemosyne:local image via shared
  build config instead of pulling from git.helu.ca
2026-05-23 19:50:29 -04:00
735eb9de1a Reset Migrations
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m8s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m12s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m24s
2026-05-23 07:14:23 -04:00
5bf9fa89cf feat: add nginx-prometheus-exporter sidecar for web metrics
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m13s
CVE Scan & Docker Build / build-and-push (push) Successful in 47s
2026-05-23 07:05:18 -04:00
8b2dcf01c1 ci(docs): rename deploy secrets/vars to CLIO_* naming
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 3m6s
Build & Deploy Docs / build-and-deploy (push) Successful in 1m13s
CVE Scan & Docker Build / build-and-push (push) Successful in 48s
2026-05-23 06:28:11 -04:00
f8a2cf0c3d docs: add Sphinx documentation build and deploy workflow
Some checks failed
CVE Scan & Docker Build / security-scan (push) Successful in 3m12s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m38s
Build & Deploy Docs / build-and-deploy (push) Failing after 1m31s
- Add Gitea Actions workflow to build and deploy docs on push to main
- Generate Sphinx reference documentation for all apps and modules
- Deploy versioned and latest docs via rsync over SSH
2026-05-23 06:11:05 -04:00
50dffe688b feat(library): register IngestJob admin and link Neo4j views
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 52s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m24s
- Add read-only ModelAdmin for IngestJob with filters, search, and
  date hierarchy for operational visibility
- Inject proxy entries into the admin index for Neo4j-backed entities
  (Libraries, Concepts, Search, Embedding pipeline) that link to
  existing CRUD views in library/views.py
- Makes library content discoverable from /admin/ without pretending
  neomodel StructuredNodes are Django ORM models
2026-05-22 23:54:10 -04:00
409da7d109 docs: replace daedalus-service basic auth with per-user DRF tokens
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 56s
CVE Scan & Docker Build / build-and-push (push) Successful in 3m30s
2026-05-22 22:59:59 -04:00
7296b8c42f CLAUDE.md added 2026-05-22 21:17:01 -04:00
55551fe9af Docs: Mnemosyne MCP
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 50s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m39s
2026-05-21 05:55:45 -04:00
e1545139ab Bug: Another attempt at fixing static.
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 1m11s
CVE Scan & Docker Build / build-and-push (push) Successful in 1m23s
2026-05-17 15:47:21 -04:00
9f6176c478 feat(models): increase max_length for source and file_type fields
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 1m0s
CVE Scan & Docker Build / build-and-push (push) Successful in 3m4s
Increase max_length for source and file_type fields in IngestJob model from 50 to 100.
This prevents data truncation for longer source references or file type strings.
2026-05-16 19:25:12 -04:00
f88ec30110 feat: enable environment variable overrides for static and media roots
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 50s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m25s
Update STATIC_ROOT and MEDIA_ROOT in settings.py to read from
environment variables with default fallbacks to BASE_DIR paths.
This allows flexible deployment configurations without modifying
source code for different environments.
2026-05-16 19:12:20 -04:00
4fb3676204 chore(docker): migrate static and media to managed, update comments
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 1m11s
CVE Scan & Docker Build / build-and-push (push) Successful in 48s
The static volume is now Docker-managed, removing the need for Ansible to create the host path. Media volume comments updated to reflect S3 storage usage (USE_LOCAL_STORAGE=False) and that the volume is effectively unused in production.
2026-05-16 19:00:16 -04:00
2a45cb2622 chore: add /mcp/health filter and configure uvicorn.access logging
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 53s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m29s
Add /mcp/health to suppress paths in log_filters.py to demote health
probe logs to DEBUG level. Configure uvicorn.access logger in settings.py
to manage access logs directly instead of relying on mcp_server internal
filters. Update comments to reflect that uvicorn access is now managed
in project settings.
2026-05-16 18:19:58 -04:00
9629ca595d refactor(startup): move startup probe to gunicorn worker init
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 51s
CVE Scan & Docker Build / build-and-push (push) Successful in 2m48s
Move probe execution from Django app ready() to gunicorn.conf.py
Remove threading implementation to simplify startup sequence
Ensure probe runs in worker process context with proper error handling
2026-05-15 10:50:35 -04:00
a3d017a70d refactor: move startup probe to daemon thread with 10s timeout
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 1m1s
CVE Scan & Docker Build / build-and-push (push) Successful in 3m15s
Move the _run_startup_probe logic into a separate daemon thread
within LibraryConfig.ready. This prevents indefinite blocking on
startup while maintaining a 10-second wait for the probe result.
2026-05-15 10:05:09 -04:00