title: Local Dev Setup — Full Test Plan
tags: [plan, testing, infrastructure, local-dev, infisical, rustfs, mongodb, pantry]
created: 2026-05-26
updated: 2026-05-27
status: active
related:
Scope: End-to-end verification of Infisical, RustFS, MongoDB, Database API, SDK, Pantry, and Endpoints running locally.
Current State
Infisical: running at localhost:8192
RustFS: running at localhost:9000 (S3) / localhost:9001 (console)
MongoDB: running (via Docker compose)
Database API (backend-app-1): crash-looping — Docker image has old SDK missing load_env. Must rebuild before any integration test works.
Caddy: running on ports 80/443
Mongo Express: running at localhost:8081
Tier 0: Fix the Blocker
Rebuild Database API Docker image
cd pipeline/backend/database && just docker-build
The current image imports load_env from sdk.environ, but the baked-in SDK only has load_dotenv. Without this fix, no endpoint or integration test can reach the database.
Tier 1: Infrastructure Layer (no GPU needed)
These validate that the three core services are reachable and correctly configured.
1.1 Test Infisical Connectivity
Run a Python snippet that calls load_env() from the SDK and prints all 9 secrets:
from sdk.environ import load_envload_env()import osfor key in ["API_URL", "API_KEY", "R2_ENDPOINT_URL", "R2_ACCESS_KEY_ID", "R2_SECRET_ACCESS_KEY", "RUNPOD_API_KEY", "OLLAMA_API_KEY", "LINEAR_API_KEY", "GITHUB_TOKEN"]: val = os.environ.get(key, "<MISSING>") print(f" {key}={val[:20]}..." if len(val) > 20 else f" {key}={val}")
Pass criteria: All 9 secrets resolve. No <MISSING> values.
Key risk:R2_ENDPOINT_URL might point at Cloudflare R2 instead of localhost:9000. Verify/update in Infisical dashboard at http://localhost:8192 → project lemna-platform → environment dev.
Pass criteria: List buckets succeeds, put/get/delete round-trip works. Bucket lemna-data exists (create via aws s3 mb or RustFS console if not).
1.3 Test MongoDB Connectivity
from pymongo import MongoClientclient = MongoClient("mongodb://localhost:27017", serverSelectionTimeoutMs=5000)client.server_info()db = client["lemna"]db["_test"].insert_one({"ok": True})assert db["_test"].find_one({"ok": True}) is not Nonedb["_test"].drop()print("MongoDB round-trip OK")
Pass criteria: Insert, find, drop succeeds.
1.4 Test Database API
After rebuilding the image and restarting:
# Restart with fresh imagecd pipeline/backend && docker compose up -d app# Wait for itcurl -s http://localhost:8000/docs | head -5
Then test CRUD with X-API-KEY header (value from Infisical API_KEY secret):
POST /jobs — create a job
PATCH /jobs/{id} — update status
POST /jobs/query — query by project/type/status
POST /jobs/get — get by ID list
DELETE /jobs/{id} — delete
Pass criteria: All routes return expected status codes. API key auth works (reject without header, accept with header).
Tier 2: SDK Integration Tests (no GPU needed)
Note: The backend integration test suite (pipeline/backend/tests/) has been removed. SDK tests should be run from pipeline/backend/lemna-sdk/tests/. The tests below are preserved as documentation of what was covered.
Tests formerly covered:
Test
What it exercises
test_submit_and_update
Job lifecycle: submit → RUNNING → COMPLETED
test_query
Query by project_name/job_name
test_get_by_id
Retrieve by ID
test_wait_polls_until_completion
Polling wait mechanism
test_failed_job
FAILED status + log field
test_submit_with_binary_file
CAS dehydrate/hydrate via S3
test_delete_job
Delete + CAS purge
test_cache_hit_returns_same_id
Input hash caching
test_no_cache_creates_new_job
Cache bypass
test_failed_job_recovery
Retry after failure
test_update_nonexistent_job
404 error handling
test_status_transition_flow
QUEUED → RUNNING → COMPLETED
test_concurrent_submissions
Thread-safety
test_query_by_status
Status-based filtering
Pass criteria: All 11 pass. This exercises SDK client + Database API + S3 CAS end-to-end.
2.2 Manual CAS Round-Trip
from sdk.cas import ContentStorefrom sdk.dtypes import BinaryFilecas = ContentStore("tests")key = cas.put(b"test payload")data = cas.get(key)assert data == b"test payload"bf = BinaryFile(path="test.bin", content=b"hello cas")cas.dehydrate(bf)assert bf.content is Noneassert bf.storage_key is not Nonecas.hydrate(bf)assert bf.content == b"hello cas"print("CAS round-trip OK")
Pass criteria: Put/get works. Dehydrate clears content and sets storage_key. Hydrate restores content from S3.
Tier 3: Pantry Tests (no GPU needed)
3.1 Test pantry add / pantry status
cd pipeline/services/endpoint-pestopantry status # show current entriespantry add . # add all untracked matching .datapatternpantry status # verify new entries appear
Pass criteria:.datapattern matching works. New entries show as added.
3.2 Test pantry push
pantry push --dry-run # previewpantry push # upload to RustFSpantry status # entries should show as `synced`
Verify objects in RustFS:
aws s3api list-objects-v2 --bucket lemna-data --endpoint-url http://localhost:9000 --no-sign-request# or check at http://localhost:9001 (RustFS console)
Pass criteria: Files uploaded. Manifest updated with storage_key. Status shows synced.
3.3 Test pantry pull
# Delete a pushed file from diskrm data/some_model.pt # (pick a safe test file)pantry pull data/some_model.pt# Verify file restored and hash matchespantry verify
Pass criteria: File downloaded from RustFS. SHA-256 hash matches manifest. Verify shows no mismatches.
Pass criteria: Returns local path when file exists. Raises DataNotAvailableError when file is deleted from disk (needs pull). Works after pull.
3.5 Test pantry extern
# From a consumer projectpantry add data/shared_file.pt --extern pesto-modelspantry resolve data/shared_file.pt # should follow extern to pesto-models namespace
Pass criteria: Cross-namespace resolution works. Extern entries show e in pantry tree.
3.6 Test pantry gc
# After pushing and removing some manifest entriespantry gc # list orphaned objectspantry gc --prune # delete orphaned objects from S3
Pass criteria: Orphaned objects detected. Prune removes them from S3.
# Endpoint tests are now run from each endpoint's own tests/ directory# e.g. pipeline/services/endpoint-pesto/tests/HAS_GPU=1 uv run pytest test_endpoint.py -v