Status: Phase 1 Baseline Complete, Phase 2-4 In Progress
Last Updated: 2026-02-21
This document is the single source of truth for:
- Unified requirements from both provided specs.
- Conflict resolution decisions.
- Implementation plan and progress log.
- Quality gates and verification status.
MEMORY_DECISION_ENGINE_SPEC (1).md(v1.0, formula/rule-driven baseline)MEMORY_DECISION_ENGINE_SPEC_v2_INTELLIGENT.md(v2.0, learned/intelligent-first)
- v2 is authoritative for behavior where v1 and v2 conflict.
- v1 remains authoritative for engineering rigor: testing discipline, documentation depth, and delivery quality gates.
- Decision mechanism
- v1: deterministic heuristic formulas.
- v2: no heuristic decision logic.
- Resolution: production decisions are learned/embedding/LLM-driven. Deterministic math is used only for feature transforms or fallback bootstrap behavior before model warm-up.
- Entity extraction
- v1: heuristic/rule-based extraction.
- v2: LLM semantic extraction only.
- Resolution: default implementation uses semantic provider interfaces and LLM-backed extraction. Test doubles are used in unit tests.
- Decay policy
- v1: hardcoded event-type half-lives.
- v2: learned decay from outcomes.
- Resolution: learned decay is primary. Any initial decay seed is explicitly treated as cold-start prior, then continuously updated.
- Retrieval ranking
- v1: formula scoring.
- v2: learned ranker.
- Resolution: learned ranking model is primary. Similarity-only fallback is allowed until ranker has enough observations to train.
- Project structure naming
- v1:
src/memory_engine/*stage folders. - v2:
src/decision_engine/*intelligent modules. - Resolution: adopt v2 module layout under
src/decision_engine/and preserve v1 quality expectations for tests/docs.
- Python 3.11+
- Strict typing and clear interfaces
- Deterministic tests for core logic
- High coverage target (90%+ initial target, move to 95%+ as implementation matures)
- Separation of concerns across encoding, importance, decay, ranking, storage
- Explainable decisions with trace metadata
- Scaffold project and quality tooling.
- Implement core intelligent modules:
- semantic encoding
- learned importance model
- learned decay learner
- learned retrieval ranker
- storage manager
- Build end-to-end orchestration API.
- Add unit/integration/lab tests for learning behavior.
- Expand docs and run quality gates.
- Reviewed both specs in full.
- Defined precedence and conflict-resolution policy.
- Established this file as the single build/spec log.
- Began project scaffolding under
src/decision_engineandtests/.
- Added project scaffolding and quality/tooling files:
pyproject.tomlREADME.md.env.exampleMakefile.gitignore
- Implemented typed core modules:
src/decision_engine/config.pysrc/decision_engine/models.pysrc/decision_engine/math_utils.pysrc/decision_engine/semantic_encoding.pysrc/decision_engine/importance_model.pysrc/decision_engine/decay_learner.pysrc/decision_engine/retrieval_ranker.pysrc/decision_engine/storage_manager.pysrc/decision_engine/engine.pysrc/decision_engine/observability.py
- Implemented initial test coverage:
tests/unit/test_semantic_encoding.pytests/unit/test_importance_model.pytests/unit/test_decay_learner.pytests/unit/test_retrieval_ranker.pytests/integration/test_engine_flow.py
- Learned-first behavior
- Importance decisions come from a neural model (
ImportanceModel). - Retrieval ordering comes from a learned ranker (
RetrievalRanker) after warm-up. - Decay rates are updated from outcome observations (
DecayLearner).
- Cold-start behavior
- Confidence thresholds are retained as explicit cold-start priors from config.
- Ranker uses semantic similarity fallback before minimum training samples.
- Offline development support
- Deterministic embedding + context semantic providers are included for local testing.
- OpenAI providers are implemented behind interfaces for production wiring.
- Initial baseline run:
python -m pytest -q: PASS (6 passed)python -m mypy src: PASS (no issues found)
- Tooling state at that moment:
pytest-covandruffwere not yet available locally.
- Core engine path is operational:
- event -> semantic encoding -> importance prediction -> storage decision -> persistence
- query -> candidate retrieval -> learned ranking -> top-k response
- feedback -> ranker training + importance training + decay updates + outcome persistence
- Strict typing passes for all source modules.
- Baseline test suite passes for unit + integration core flows.
- External LLM provider default: OpenAI-only for now; Anthropic adapter can be added after base flow is stable.
- Vector index backend: numpy exact-search fallback first; FAISS integration behind optional dependency.
- Core modules compile and are testable locally.
- End-to-end flow works with pluggable providers and local test doubles.
- Baseline unit/integration tests pass.
- This document updated with each major implementation step.
Implemented:
- Full v1-compatible staged package layout under
src/memory_engine/. - Stage modules:
stage1_input: embedding provider builder, semantic extractor, input processorstage2_decision: learned scoring, learned decay assignment, compression planner, decision logicstage3_learning: feedback model, weight updater, learning loop
- Orchestrator:
src/memory_engine/engine.pywith API:process_inputmake_storage_decisionstore_memoryretrieverecord_outcomerecord_feedbackget_memorymemory_count
Implemented:
- Compression workflow with replacement semantics:
- compressed records track
is_compressedandoriginal_count.
- compressed records track
- Vector store abstraction:
src/memory_engine/storage/vector_store.py- optional FAISS backend + numpy fallback.
- SQLAlchemy DB module:
src/memory_engine/storage/db.py
- Retrieval service layer:
src/memory_engine/storage/retrieval.py
- Metrics/observability:
- batched metrics flush to
metrics.json - JSON event logs via engine logger facade.
- batched metrics flush to
Implemented:
- Required documentation files:
docs/ARCHITECTURE.mddocs/FORMULAS.mddocs/TESTING.md
- Required scripts:
scripts/generate_test_data.pyscripts/run_lab_tests.pyscripts/dashboard.py
- Expanded test suite across required folders:
tests/unit/tests/integration/tests/benchmarks/tests/lab/
Implemented:
- Lint/type/format/test toolchain in place:
ruff,mypy,black,pytest,pytest-cov
- Poetry installed and lockfile generated:
poetry.lockpoetry lockexecuted successfully
Current verification results:
python -m black --check src tests: PASSpython -m ruff check src tests: PASSpython -m mypy src: PASSpython -m pytest -q: PASS (32 passed)python -m pytest --cov=src --cov-report=term-missing -q: PASS (TOTAL 95%)
Ready:
- Unit tests: PASS
- Integration tests: PASS
- Benchmark tests: PASS
- Lab tests: PASS
- Coverage >= 95%: PASS
- Mypy strict: PASS
- Ruff lint: PASS
- Black format check: PASS
- Single-source implementation log: PASS (
BUILD_AND_SPEC.md) - Architecture/formulas/testing docs: PASS
.env.example: PASSpoetry.lock: PASS
Remaining for strict literal parity with both original specs:
- Anthropic/Gemini/Ollama semantic adapters are not yet implemented in code.
Completed:
- Added
.pylintrcfocused on correctness-oriented linting while suppressing low-signal style/design noise. - Ran
python -m pylint src --fail-under=9.0and passed with10.00/10. - Migrated
pyproject.tomlmetadata from deprecated[tool.poetry.*]fields to modern[project]metadata. - Kept Poetry-specific
packagesdefinition under[tool.poetry]forsrc/package discovery. - Regenerated lockfile (
poetry lock) and verified metadata (poetry check->All set!). - Fixed embedding-dimension alignment:
- OpenAI embedding provider now accepts explicit
dimensions. - Stage 1 embedding factory passes
embedding_diminto OpenAI embedding requests to avoid shape mismatch with learned models/vector index.
- OpenAI embedding provider now accepts explicit
- Added provider registry + adapter scaffolding:
src/memory_engine/providers/registry.pysrc/memory_engine/providers/adapters.py- Provider selection via env:
MDE_EMBEDDING_PROVIDERMDE_SEMANTIC_PROVIDER
- Optional adapters scaffolded for:
- Anthropic
- Gemini
- Ollama
- Optional dependency extras added in
pyproject.toml:anthropic,gemini,ollama,llm-adapters
- Upgraded Anthropic embedding adapter from scaffold to functional path:
AnthropicEmbeddingProvidernow performs a real API call via Anthropicmessages.create, requests a JSON embedding payload, coerces dimensions, and normalizes vectors.
- Replaced logger backend with strict
structlogJSON logging:src/decision_engine/observability.pynow configuresstructlogglobally and emits structured JSON forinfo,warning, anderrorevents.
Post-migration verification:
python -m black --check src tests: PASSpython -m ruff check src tests: PASSpython -m mypy src: PASSpython -m pylint src --fail-under=9.0: PASS (10.00/10)python -m pytest -q: PASS (44 passed)python -m pytest --cov=src --cov-report=term-missing -q: PASS (TOTAL 95%)
Completed:
- Implemented public SDK package
src/orbit/:MemoryEngine(sync)AsyncMemoryEngine(async)Configdefaults + env loading- Typed Pydantic request/response models
- Exception hierarchy (
OrbitAuthError,OrbitValidationError,OrbitRateLimitError, etc.) - HTTP layer (
httpx) with automatic retries and exponential backoff - Structured logging (
structlog) and telemetry hook
- Implemented REST API package
src/orbit_api/with FastAPI:POST /v1/ingestGET /v1/retrievePOST /v1/feedbackPOST /v1/ingest/batchPOST /v1/feedback/batchGET /v1/statusGET /v1/healthGET /v1/metricsPOST /v1/auth/validateGET /v1/memories(cursor pagination)
- Added Bearer token validation (
orbit_pk_+ 32-char suffix) and quota-based rate limiting with standard rate headers. - Added integration wiring from API into existing intelligent core (
memory_engine.engine.DecisionEngine). - Added SDK/API tests and examples:
tests/unit/test_orbit_http.pytests/unit/test_orbit_client.pytests/unit/test_orbit_async_client.pytests/unit/test_orbit_models.pytests/integration/test_orbit_api_integration.pyexamples/*.pyusage patterns
Storage status after this phase:
- Active storage backend is SQLite (
SQLiteStorageManager) with embedding vectors and metadata persisted inmemoriestable. - Vector retrieval uses in-memory index with persisted index artifact (
.idx) when configured. - SQLAlchemy schema module exists (
src/memory_engine/storage/db.py) and can be extended for PostgreSQL migration, but full production PostgreSQL API runtime is not yet completed in this phase.
Verification after SDK/API integration + performance stabilization:
python -m black src tests examples docs --check: PASSpython -m ruff check src tests examples: PASSpython -m mypy src: PASSpython -m pylint src --fail-under=9.0: PASS (9.99/10)python -m pytest -q: PASSpython -m pytest --cov=src --cov-report=term-missing -q: PASS (TOTAL 91%)
Recent runtime hardening included:
- SQLite threading compatibility for FastAPI worker execution (
check_same_thread=False). - Faster vector-store numpy fallback search path with cached matrix/index mapping.
- Reduced retrieval candidate pool default to improve p99 latency in benchmark paths.
Completed:
- PostgreSQL-first API runtime and migration path:
- Added
database_urlsupport to engine config (MDE_DATABASE_URL). - Added SQLAlchemy-backed storage manager:
src/decision_engine/storage_sqlalchemy.py- shared storage interface:
src/decision_engine/storage_protocol.py
- Wired staged decision engine to choose SQLAlchemy storage when
database_urlis set. - Added Alembic migration stack:
alembic.inimigrations/env.pymigrations/versions/20260221_0001_create_memories_table.py
- Added startup migration execution in API entrypoint (
ORBIT_AUTO_MIGRATE).
- Added
- Strict JWT verification + hard slowapi integration:
- Replaced API-key pattern auth with strict JWT validation:
src/orbit_api/auth.py- required claims:
sub,iat,exp,iss,aud - optional required scope enforcement (
ORBIT_JWT_REQUIRED_SCOPE)
- Hard-wired slowapi imports and middleware in FastAPI app.
- Per-day quota headers + per-minute slowapi limits now operate together.
- Replaced API-key pattern auth with strict JWT validation:
- Deployment bundle:
Dockerfiledocker-compose.yml(Orbit API + PostgreSQL + Prometheus + OTel Collector)scripts/docker-entrypoint.sh- Prometheus config:
deploy/prometheus/prometheus.yml - OTel collector config:
deploy/otel/otel-collector-config.yaml - Added OTel bootstrap module:
src/orbit_api/telemetry.py
- Live testing scaffold (Orbit + Ollama chatbot):
examples/live_chatbot_ollama/app.pyexamples/live_chatbot_ollama/smoke_test.pyexamples/live_chatbot_ollama/README.md- JWT generation utility for local runs:
scripts/generate_jwt.py
Storage status after this phase:
- API runtime now supports PostgreSQL-backed persistence via SQLAlchemy manager and defaults to PostgreSQL DSN in API config.
- SQLite remains available for local/test fallback via SQLite URL.
- Vector retrieval still uses in-process vector index + learned ranker over persisted memory records.
Verification:
python -m black src tests examples docs --check: PASSpython -m ruff check src tests examples docs: PASSpython -m mypy src: PASSpython -m pylint src --fail-under=9.0: PASS (9.99/10)python -m pytest -q: PASSpython -m pytest --cov=src --cov-report=term-missing -q: PASS (TOTAL 90%)poetry lock: PASSpoetry check: PASS
Root cause identified:
- Untrained retrieval fallback was effectively similarity-only, so long assistant responses often dominated top-k.
- Stage-1 default summaries used full event text when no summary metadata was provided.
- Semantic text embedding included full content payloads, amplifying long-response dominance.
Implemented fix:
- Retrieval ranker hardening (
src/decision_engine/retrieval_ranker.py):- Expanded ranking features from 5 to 8 with:
latest_importance- length penalty (summary/content size)
- intent prior (downweight
assistant_response, boost profile/progress intents)
- Replaced similarity-only cold-start scoring with weighted heuristic fallback.
- Added trained-score blending with fallback prior for stability.
- Expanded ranking features from 5 to 8 with:
- Stage-1 summary compaction (
src/memory_engine/stage1_input/processor.py):- Added concise default summary derivation when metadata summary is absent.
- Strips
Assistant response:prefix, picks first sentence, clamps length.
- Semantic embedding text clipping (
src/decision_engine/semantic_encoding.py):- Clipped summary/content used for semantic embedding input to prevent long-text over-dominance.
New regression coverage:
tests/unit/test_retrieval_ranker.py:test_ranker_downweights_long_assistant_responses_pre_warmup
tests/unit/test_stage1.py:test_stage1_compacts_default_assistant_response_summary
Verification:
pytest tests/unit/test_retrieval_ranker.py tests/unit/test_stage1.py -q: PASSpytest -q: PASSruff check(touched files): PASSmypy(touched files): PASSpylint src --fail-under=9.0: PASS (9.95/10)
Implemented:
- Added repeatable stress harness:
scripts/stress_audit.py
- Harness runs seven scenarios and writes both machine and human reports:
stress_audit_report.jsonstress_audit_report.md
Executed command:
PYTHONPATH=src python scripts/stress_audit.py --output-dir stress_reports/run_20260222
Audit outputs:
stress_reports/run_20260222/stress_audit_report.jsonstress_reports/run_20260222/stress_audit_report.md
Key findings from this run:
- Throughput/retrieval baseline (core engine path) passed up to 10k memories:
- ingest ~135 events/sec at 10k corpus
- retrieve p95 ~66ms
- Storage bloat warning:
- long assistant responses persisted in full (
avg_content_chars ~6832) - DB size ~5.88MB for 250 memories (~24.7KB per memory)
- summaries were compact, but full
contentstill retained
- long assistant responses persisted in full (
- Relevance under heavy mixed-chatbot noise warned:
- precision@5 = 0.10 in synthetic noisy profile-vs-assistant corpus
- assistant_response memories dominated many top-5 slots
- Entity isolation passed:
- no cross-entity leaks observed with API
entity_idfiltering
- no cross-entity leaks observed with API
- Feedback adaptation passed:
- repeated positive feedback converged preferred memory to top rank
- Concurrent ingest pressure failed (SQLite path):
- 258 failed writes out of 2640 attempts in core-engine concurrent test
- additional API-level heavy concurrency test also reproduced failures with
sqlite3.OperationalError: database is locked
- Compression passed for repetitive traffic:
- compression ratio ~0.80 with repetitive assistant_response stream
Additional scaling probe (API retrieval path):
- 5k memories: p50 ~526ms, p95 ~660ms
- 10k memories: p50 ~1021ms, p95 ~1278ms
- This indicates API retrieval path (full candidate scan + ranking) scales materially worse than core retrieval benchmark path.
Scope:
- Remediated each stress finding in engineering phases, with extra focus on storage efficiency for long assistant responses.
Implemented remediation:
- Storage efficiency hardening:
- Added compact embedding vector codec:
src/decision_engine/vector_codec.py- stores vectors as float16 base64 payloads with backward-compatible JSON decode.
- Wired both storage backends to use compact vector encoding:
src/decision_engine/storage_manager.pysrc/decision_engine/storage_sqlalchemy.py
- Kept backward compatibility for legacy JSON vector rows.
- Lowered assistant content persistence defaults to tighter cap across engine-backed writes.
- Added compact embedding vector codec:
- Retrieval-noise remediation:
- Tightened assistant-response ranking priors and length penalties:
src/decision_engine/retrieval_ranker.py
- Lowered default assistant top-k share:
src/decision_engine/config.py(assistant_response_max_share=0.25)
- Enforced stricter assistant share capping and added candidate diversification:
src/memory_engine/storage/retrieval.pysrc/orbit_api/service.py
- Retrieval now enriches candidate pool with non-assistant memories when vector preselection is overly assistant-heavy.
- Tightened assistant-response ranking priors and length penalties:
- Stress harness correctness:
- Fixed storage scenario pass/warn/fail logic to reflect true truncation and footprint behavior:
scripts/stress_audit.py
- Fixed storage scenario pass/warn/fail logic to reflect true truncation and footprint behavior:
New test coverage:
tests/unit/test_vector_codec.py- float16 payload round-trip
- legacy JSON decode compatibility
- invalid payload handling
tests/unit/test_retrieval_service.py- assistant-share cap behavior with mixed candidates
- fallback behavior when only assistant memories are available
Verification:
python -m pytest -q: PASSpython -m ruff check src tests scripts: PASSpython -m mypy src: PASSpython -m pylint src tests scripts --fail-under=9.0: PASS (9.91/10)
Final remediation stress run:
- Command:
PYTHONPATH=src python scripts/stress_audit.py --output-dir stress_reports/run_20260222_remediate4
- Output:
stress_reports/run_20260222_remediate4/stress_audit_report.jsonstress_reports/run_20260222_remediate4/stress_audit_report.md
- Result:
- All scenarios PASS.
- Storage efficiency outcome (long assistant responses):
avg_content_chars ~901.9(truncated)db_size ~0.988 MBfor 250 memoriesbytes_per_memory ~4145.2(down from ~24674 baseline)
- Relevance/noise outcome:
avg_precision@5 = 0.85assistant_slots_in_top5_total = 3- personalization memories remain dominant under mixed noisy chatbot traffic.
Goal:
- Move from retrieval-only adaptation to profile-level inferred memory synthesis, with developer-first integration docs.
Implemented:
- Added adaptive personalization inference engine:
src/memory_engine/personalization/adaptive.pysrc/memory_engine/personalization/__init__.py
- Inference types now generated automatically:
inferred_learning_pattern:- Triggered by repeated semantically similar user patterns for same entity.
inferred_preference:- Triggered by repeated positive feedback on assistant response style.
- Integrated inference into core engine lifecycle:
- Post-store observation:
src/memory_engine/engine.pycalls personalization observer after normal memory writes.
- Post-feedback observation:
src/memory_engine/engine.pycalls personalization observer after learning loop updates.
- Inferred memories are persisted as first-class memories and indexed in vector store for retrieval.
- Post-store observation:
- Added personalization runtime controls to core config:
enable_adaptive_personalizationpersonalization_repeat_thresholdpersonalization_similarity_thresholdpersonalization_window_dayspersonalization_min_feedback_eventspersonalization_preference_margin- Env vars added in
.env.example.
- Retrieval tuning for inferred memories:
- Added intent priors for inferred intents in
src/decision_engine/retrieval_ranker.py.
- Added intent priors for inferred intents in
- Developer docs and examples:
- New guide:
docs/personalization.md - Updated:
docs/quickstart.mddocs/api_reference.mddocs/examples.mddocs/troubleshooting.mdREADME.mdexamples/live_chatbot_ollama/README.md
- New runnable example:
examples/personalization_quickstart.py
- New guide:
New tests:
tests/integration/test_adaptive_personalization.py- repeated-question inferred pattern creation
- dedupe for repeated-topic inferred pattern
- feedback-driven inferred preference creation
- Updated config tests:
tests/unit/test_decision_config.pytests/unit/test_feedback_and_config.py
Validation:
python -m ruff check src tests examples scripts: PASSpython -m mypy src: PASSpython -m pytest -q: PASSpython -m pylint src tests scripts --fail-under=9.0: PASS (9.91/10)
Post-personalization stress audit:
- Command:
PYTHONPATH=src python scripts/stress_audit.py --output-dir stress_reports/run_20260222_personalization_v2
- Output:
stress_reports/run_20260222_personalization_v2/stress_audit_report.jsonstress_reports/run_20260222_personalization_v2/stress_audit_report.md
- Result:
- All scenarios PASS, including feedback convergence.
Completed:
- Added canonical single-file developer integration documentation:
DEVELOPER_DOCUMENTATION.md
- The new document consolidates:
- SDK integration
- REST API integration
- JWT/auth contract
- adaptive personalization behavior and tuning
- deployment and local self-host path
- operations/monitoring
- troubleshooting and production checklist
- Updated documentation entry points:
README.mdnow points to canonical developer docs.docs/index.mdnow points to canonical developer docs.
Completed:
- Added GitHub Pages deployment workflow:
.github/workflows/docs-pages.yml- Builds Sphinx docs from
docs/and deploys to GitHub Pages onmain.
- Standardized docs-site source of truth:
- Full canonical developer guide now lives in:
docs/developer_documentation.md
- Root file
DEVELOPER_DOCUMENTATION.mdis now a pointer to docs-site canonical file.
- Full canonical developer guide now lives in:
- Improved docs navigation for published site:
docs/index.mdnow uses a MyST/Sphinxtoctree.
- Added docs build artifact ignore:
.gitignoreincludesdocs/_build/.
Operator step required in GitHub UI:
- Repository Settings -> Pages -> Source: GitHub Actions.
Context:
- GitHub Actions execution was blocked by account billing lock.
- Switched docs hosting to branch-based Pages deployment.
Completed:
- Removed Actions-based Pages workflow:
.github/workflows/docs-pages.yml
- Made docs landing page Jekyll/GitHub Pages friendly:
docs/index.mdnow uses plain markdown links (no Sphinx-only directives).
- Added Pages branch setup runbook:
docs/GITHUB_PAGES_SETUP.md
- Added Jekyll config for docs site:
docs/_config.yml
- Updated docs entrypoint in README:
README.mdnow references branch-based Pages setup.
Operator step required in GitHub UI:
- Repository Settings -> Pages -> Build and deployment:
- Source: Deploy from a branch
- Branch:
main - Folder:
/docs
Completed:
- Added standalone OpenClaw plugin scaffold package:
integrations/openclaw-memory/package.jsonintegrations/openclaw-memory/tsconfig.jsonintegrations/openclaw-memory/openclaw.plugin.jsonintegrations/openclaw-memory/README.mdintegrations/openclaw-memory/src/index.tsintegrations/openclaw-memory/src/config.tsintegrations/openclaw-memory/src/orbit-client.tsintegrations/openclaw-memory/src/identity.tsintegrations/openclaw-memory/src/format.tsintegrations/openclaw-memory/src/types.ts
- Plugin capabilities scaffolded:
- OpenClaw memory slot metadata (
category: memory,slots.memory) before_agent_starthook retrieves Orbit context and appends to prompt inputagent_endhook ingests user input + assistant output into Orbit- utility command/tool bindings:
orbit-memory-statusorbit_recallorbit_feedback
- OpenClaw memory slot metadata (
- Developer documentation updated:
docs/developer_documentation.mdincludes OpenClaw integration mode and quickstartREADME.mdpoints to the OpenClaw plugin scaffold
Validation:
cd integrations/openclaw-memory && npm install: PASScd integrations/openclaw-memory && npm run typecheck: PASScd integrations/openclaw-memory && npm run build: PASS
Completed:
- Added root metadata document:
metaData.md
- Content includes:
- project identity and summaries
- SEO keyword clusters
- suggested GitHub topics
- technologies, libraries, packages
- API/SDK keyword surfaces
- architecture and integration discovery terms
- Added repository pointer:
README.mdnow referencesmetaData.md.
Completed:
- Resolved strict TypeScript compile blockers in OpenClaw plugin:
- fixed
exactOptionalPropertyTypesload-config call path in:integrations/openclaw-memory/src/index.ts
- fixed strict indexing nullability in:
integrations/openclaw-memory/src/identity.ts
- fixed
- Strengthened entity identity resolution:
sessionKey-first resolution with fallback behavior controls- alias collapsing via
identityLinks - channel-aware prefixed fallback IDs
- implemented in:
integrations/openclaw-memory/src/identity.tsintegrations/openclaw-memory/src/config.tsintegrations/openclaw-memory/src/index.tsintegrations/openclaw-memory/openclaw.plugin.json
- Added mocked test suite (Vitest):
integrations/openclaw-memory/src/__tests__/identity.test.tsintegrations/openclaw-memory/src/__tests__/config.test.tsintegrations/openclaw-memory/src/__tests__/plugin.test.ts- coverage includes:
- identity stitching behavior
- config merge behavior (runtime/env/plugin)
- hook lifecycle (
before_agent_start+agent_end) with mocked Orbit API - command registration and status path
- Updated integration docs:
integrations/openclaw-memory/README.md
- npm packaging hardening:
- made
openclawpeer optional viapeerDependenciesMetain:integrations/openclaw-memory/package.json
- regenerated lockfile with optional-peer behavior:
integrations/openclaw-memory/package-lock.json
- removed previous peer-induced lockfile bloat and audit noise
- made
Validation:
cd integrations/openclaw-memory && npm run typecheck: PASScd integrations/openclaw-memory && npm run test: PASS (3 files, 8 tests)cd integrations/openclaw-memory && npm run build: PASScd integrations/openclaw-memory && npm run validate: PASScd integrations/openclaw-memory && npm install: PASS (0 vulnerabilities)
Completed:
- Hardened Orbit API runtime config:
- Added environment-aware auth and guardrail settings in
src/orbit_api/config.py:ORBIT_ENV(development|production)ORBIT_MAX_INGEST_CONTENT_CHARSORBIT_MAX_QUERY_CHARSORBIT_MAX_BATCH_ITEMSORBIT_USAGE_STATE_PATH
- Added strict validation:
- Reject
jwt_algorithm=none - Enforce non-default
ORBIT_JWT_SECRETin production (ORBIT_ENV=production) - Positive-integer validation for runtime limits
- Reject
- Added environment-aware auth and guardrail settings in
- Tightened request-level API protection in
src/orbit_api/app.py:- Ingest content size hard limit enforcement
- Retrieve query max-length enforcement
- Batch request limits:
- non-empty enforcement
- max item count enforcement
- per-event ingest content cap validation for ingest batches
- Hardened service state handling in
src/orbit_api/service.py:- Added thread-safe lock for shared mutable state (
_usage_by_key, metrics, latest ingestion) - Added optional durable quota persistence across restarts:
- load on startup from
ORBIT_USAGE_STATE_PATH - persist on quota updates and shutdown
- tolerant parsing for malformed usage state files
- load on startup from
- Improved health semantics:
/v1/healthnow verifies storage readiness viamemory_count()- returns degraded state with detail on storage failure
- Added thread-safe lock for shared mutable state (
- Added model-level batch constraints in
src/orbit/models.py:IngestBatchRequest.events: min 1, max 100FeedbackBatchRequest.feedback: min 1, max 100
- Updated operator documentation:
.env.exampleincludes new hardening env varsdocs/developer_documentation.mdconfiguration reference updated
Tests Added/Updated:
tests/unit/test_orbit_config_and_entrypoint.py:- env parsing for new config fields
- production default-secret rejection
- JWT
nonealgorithm rejection
tests/unit/test_orbit_api_service.py:- durable quota persistence across service restart
- degraded health behavior on storage failure
tests/integration/test_orbit_api_errors.py:- empty ingest batch rejected
- oversized ingest batch rejected
- overlong retrieve query rejected
Validation:
python -m ruff check src tests: PASSpytest -q: PASSpylint src --fail-under=9.0: PASS (9.95/10)python -m mypy src: PASS
Completed:
- Replaced file-backed API quota state with database-backed transactional state:
- Added
ApiAccountUsageRowmodel insrc/memory_engine/storage/db.py - Added Alembic migration
migrations/versions/20260223_0002_create_api_state_tables.py OrbitApiServicenow consumes quota through DB transactions inapi_account_usage
- Added
- Implemented idempotent write execution with payload hashing and replay cache:
- Added
ApiIdempotencyRowmodel + migration tableapi_idempotency - Added request hash conflict detection (same key + different payload -> conflict)
- Added replay support for successful duplicates (same key + same payload)
- Added pending idempotency cleanup on write failure paths
- Added
- Wired idempotency into API endpoints:
POST /v1/ingestPOST /v1/feedbackPOST /v1/ingest/batchPOST /v1/feedback/batch- Added
Idempotency-Keyheader support - Added
X-Idempotency-Replayed: true|falseresponse header - Added
409 Conflictbehavior for key/payload mismatch or in-progress reuse
- Removed obsolete file-backed quota environment setting:
- removed
ORBIT_USAGE_STATE_PATHfrom runtime configuration and.env.example
- removed
Tests Added/Updated:
tests/unit/test_orbit_api_service.py:- idempotent ingest replay + conflict path
- idempotency persistence across service restart
- idempotent ingest batch replay path
tests/integration/test_orbit_api_errors.py:- API-level ingest replay + conflict validation
- API-level feedback replay + conflict validation
tests/unit/test_orbit_config_and_entrypoint.py:- removed deprecated
ORBIT_USAGE_STATE_PATHexpectations
- removed deprecated
Validation:
python -m ruff check src tests: PASSpytest -q: PASSpython -m mypy src: PASSpylint src --fail-under=9.0: PASS (9.94/10)
Completed:
- Added Render Blueprint deployment file:
render.yaml- provisions
orbit-apiweb service (Docker) +orbit-postgresmanaged database - sets production env defaults, health check path, and API runtime guardrails
- Added deployment runbook for operators and integrators:
docs/DEPLOY_RENDER_VERCEL.md- includes Render deployment steps, required env vars, smoke test flow, and Vercel server-side JWT route pattern
- Hardened container runtime for PaaS behavior:
scripts/docker-entrypoint.shnow:- respects
ORBIT_AUTO_MIGRATE - binds API port from
PORTfallback (PORT->ORBIT_API_PORT->8000)
- respects
- Added database URL normalization for Render-style connection strings:
- new utility
src/decision_engine/database_url.py postgres://...andpostgresql://...are normalized topostgresql+psycopg://...- wired into:
src/decision_engine/config.pysrc/orbit_api/config.pysrc/orbit_api/__main__.pymigrations/env.py
- new utility
- Added CORS configuration for browser-based frontend integration:
src/orbit_api/config.py:- new
ORBIT_CORS_ALLOW_ORIGINSsupport (comma-separated parsing)
- new
src/orbit_api/app.py:- conditional
CORSMiddlewarewiring - exposes API headers needed by clients (
X-RateLimit-*,Retry-After,X-Idempotency-Replayed)
- conditional
- Updated docs and env references:
.env.exampleincludesORBIT_CORS_ALLOW_ORIGINSdocs/developer_documentation.mdreferences hosted deployment runbookREADME.mdincludes deployment runbook link
Tests Added/Updated:
tests/unit/test_decision_config.py:- validates Render-style Postgres URL normalization
tests/unit/test_orbit_config_and_entrypoint.py:- validates
ORBIT_CORS_ALLOW_ORIGINSenv parsing - validates API config Postgres URL normalization
- validates
tests/integration/test_orbit_api_errors.py:- CORS preflight behavior for configured Vercel origin
Validation:
python -m ruff check src tests migrations scripts: PASSpytest -q: PASSpython -m mypy src: PASSpylint src --fail-under=9.0: PASS (9.94/10)
Completed:
- Tightened
pyproject.tomlpackage metadata under[project]:- switched readme to
README.mdwith explicit content type - added maintainers, keywords, classifiers
- added project URLs (
Homepage,Repository,Documentation,Issues) - added console script entry point:
orbit-api = orbit_api.__main__:main
- switched readme to
- Added GitHub Actions trusted-publishing workflow:
.github/workflows/publish-pypi.yml- triggers on
v*tags and manual dispatch - validates Git tag version matches
project.version - builds sdist/wheel and validates metadata
- publishes to PyPI using OIDC (
pypa/gh-action-pypi-publish)
Validation:
python -m build: PASSpython -m ruff check src tests: PASS
Completed:
- Added a reproducible evaluation harness for product quality validation:
src/orbit/eval_harness.py- compares a naive baseline retrieval strategy vs Orbit retrieval on the same synthetic workload
- computes scorecard metrics:
Precision@5Top1 relevant ratePersonalization hit ratePredicted helpfulness rateAssistant noise rateStale memory rate
- writes concrete artifacts:
orbit_eval_scorecard.jsonorbit_eval_scorecard.md(includes per-query retrieval ordering payload traces)
- Added CLI runner:
scripts/run_orbit_eval.py- supports configurable output path, sqlite path, embedding dimension, noise scale
- defaults to quiet mode and prints concise metrics + artifact paths
- Added unit tests for scorecard logic:
tests/unit/test_eval_harness.py- covers tokenization, baseline scoring bias behavior, per-query metric computation, aggregation
- Updated developer docs and README with evaluation usage:
docs/developer_documentation.mdREADME.md
Observed sample scorecard (local run):
- Baseline:
avg_precision_at_5=0.000assistant_noise_rate=0.950
- Orbit:
avg_precision_at_5=0.350assistant_noise_rate=0.000- still shows a literal gap on some queries (
recurring_error) and occasional stale profile surfacing
Validation:
python -m ruff check src tests: PASSpython -m mypy src: PASSpytest -q tests/unit/test_eval_harness.py: PASSpython scripts/run_orbit_eval.py --output-dir tmp/eval_sample --sqlite-path tmp/orbit_eval.db: PASS
Completed:
- Implemented query-intent-aware reweighting in API retrieval path:
src/orbit_api/service.py- new
_reweight_ranked_by_query(...)pass now runs after ranker output and before top-k intent caps - Phase 1 logic:
- boosts
inferred_learning_patternon mistake/error/repeat-focused queries - lightly boosts
learning_progresson those queries - lightly downweights assistant intents for mistake-focused queries
- boosts
- Implemented stale-profile suppression when newer progress exists:
src/orbit_api/service.py- Phase 2 logic:
- detects latest
learning_progressmemory with advancement signals - downweights older stale profile memories (e.g. beginner/novice baseline statements) when newer progress exists
- uses stronger suppression for recency/current-state queries
- detects latest
- Added focused unit tests:
tests/unit/test_orbit_api_service.pytest_service_boosts_inferred_pattern_for_mistake_queriestest_service_suppresses_stale_profile_when_newer_progress_exists
Scorecard Before/After (same eval workload):
- Before artifact:
tmp/eval_before/orbit_eval_scorecard.json
- After artifact:
tmp/eval_after/orbit_eval_scorecard.json
Orbit metric deltas (after - before):
avg_precision_at_5:+0.000(0.35 -> 0.35)top1_relevant_rate:+0.500(0.25 -> 0.75)personalization_hit_rate:+0.250(0.75 -> 1.00)predicted_helpfulness_rate:+0.250(0.75 -> 1.00)assistant_noise_rate:+0.000(0.00 -> 0.00)stale_memory_rate:+0.000(0.00 -> 0.00)
Concrete retrieval ordering improvements:
- Recurring-mistake query:
- before top-1:
preference_stated - after top-1:
inferred_learning_pattern
- before top-1:
- Day-30 architecture query:
- before top-1: stale beginner profile
- after top-1: project-learning preference / current profile signals (stale beginner no longer top-ranked)
Validation:
python -m ruff check src tests scripts: PASSpython -m mypy src: PASSpytest -q: PASSpylint src --fail-under=9.0: PASS (9.94/10)
Completed:
- Expanded adaptive personalization inference engine:
src/memory_engine/personalization/adaptive.py- added recurring-failure inference path:
- detects repeated failure signals from
user_attempt/assessment_result - writes
inferred_learning_patternmemories with remediation-oriented guidance
- detects repeated failure signals from
- added inferred progress-accumulation path:
- detects repeated positive progress/assessment signals
- writes inferred
learning_progressmemories for stage-appropriate tutoring
- added signature-based dedupe metadata persisted on relationships:
signature:<...>inference_type:<...>inferred:true
- added lexical fallback similarity + relaxed clustering threshold for failure/progress inference so semantically similar phrasing variants still cluster under local deterministic embeddings.
- Added integration coverage for new inference behavior:
tests/integration/test_adaptive_personalization.pytest_failed_attempts_create_recurring_failure_inferencetest_repeated_positive_assessments_create_progress_inference
- Updated scorecard relevance evaluation to treat inferred derivative memories as relevant when
they are token-overlap derivatives of labeled relevant context:
src/orbit/eval_harness.py- new helper logic in
evaluate_ranking(...) - test coverage:
tests/unit/test_eval_harness.pytest_evaluate_ranking_treats_inferred_derivative_as_relevant
- Updated developer documentation:
docs/developer_documentation.mdnow documents recurring-failure and inferred-progress behavior.
Scorecard regression check:
- Prior best reference:
tmp/eval_diversity_after/orbit_eval_scorecard.json
- Post-Phase-3:
tmp/eval_phase3_inferred_v3/orbit_eval_scorecard.json
- Orbit metrics:
avg_precision_at_5:0.40 -> 0.40(no regression)top1_relevant_rate:0.75 -> 0.75(no regression)personalization_hit_rate:1.00 -> 1.00(no regression)predicted_helpfulness_rate:1.00 -> 1.00(no regression)assistant_noise_rate:0.00 -> 0.00(no regression)
Validation:
python -m pytest -q: PASSpython -m ruff check src tests: PASSpython -m pylint src/memory_engine/personalization/adaptive.py src/orbit/eval_harness.py tests/integration/test_adaptive_personalization.py tests/unit/test_eval_harness.py --fail-under=9.0: PASS (9.98/10)
Completed:
- Added lifecycle configuration controls:
src/decision_engine/config.pypersonalization_inferred_ttl_days(default45)personalization_inferred_refresh_days(default14)personalization_lifecycle_check_interval_seconds(default30, supports0)
src/memory_engine/config.pynow carries these through from core config..env.exampleupdated with corresponding env vars:MDE_PERSONALIZATION_INFERRED_TTL_DAYSMDE_PERSONALIZATION_INFERRED_REFRESH_DAYSMDE_PERSONALIZATION_LIFECYCLE_CHECK_INTERVAL_SECONDS
- Implemented inferred-memory lifecycle semantics in adaptive engine:
src/memory_engine/personalization/adaptive.pyInferredMemoryCandidatenow supportssupersedes_memory_ids- signature reservation now supports:
- dedupe while fresh
- refresh when stale by returning superseded IDs
- added
expired_inferred_memory_ids()for TTL pruning - added
notify_memories_deleted(...)for signature-cache cleanup
- Wired lifecycle execution into runtime engine:
src/memory_engine/engine.py- periodic lifecycle scans on write/feedback path
- automatic TTL pruning of expired inferred memories
- supersession delete path before writing refreshed inferred memories
- unified memory delete helper to keep storage/vector/cache/persona state consistent
- Developer docs updated:
docs/developer_documentation.mdpersonalization controls table now includes lifecycle knobs.
Tests Added/Updated:
tests/integration/test_adaptive_personalization.pytest_inferred_signature_refresh_supersedes_old_memorytest_inferred_memory_ttl_expires_and_is_pruned
tests/unit/test_decision_config.py- env parsing assertions for new lifecycle config
- negative lifecycle interval validation test
Scorecard regression check:
- Reference before:
tmp/eval_phase3_inferred_v3/orbit_eval_scorecard.json
- After lifecycle phase:
tmp/eval_phase4_lifecycle/orbit_eval_scorecard.json
- Orbit metrics delta (after - before):
avg_precision_at_5:0.40 -> 0.40(+0.00)top1_relevant_rate:0.75 -> 0.75(+0.00)personalization_hit_rate:1.00 -> 1.00(+0.00)predicted_helpfulness_rate:1.00 -> 1.00(+0.00)assistant_noise_rate:0.00 -> 0.00(+0.00)stale_memory_rate:0.00 -> 0.00(+0.00)
Validation:
python -m pytest -q: PASSpython -m ruff check src/decision_engine/config.py src/memory_engine/config.py src/memory_engine/personalization/adaptive.py src/memory_engine/engine.py tests/unit/test_decision_config.py tests/integration/test_adaptive_personalization.py: PASSpython -m pylint src/decision_engine/config.py src/memory_engine/config.py src/memory_engine/personalization/adaptive.py src/memory_engine/engine.py tests/unit/test_decision_config.py tests/integration/test_adaptive_personalization.py --fail-under=9.0: PASS (10.00/10)
Completed:
- Added structured inference provenance metadata to every memory returned by API retrieve/list endpoints:
src/orbit_api/service.py- new
metadata.inference_provenanceblock includes:is_inferredwhywheninference_typesignaturederived_from_memory_idssupersedes_memory_ids
- Implemented normalization/parsing from stored relationship markers:
inference_type:<...>signature:<...>derived_from:<memory_id>supersedes:<memory_id>inferred:true
- Added default provenance for non-inferred memories so downstream debugging code has a stable shape.
- Improved inferred candidate persistence to include supersession markers:
src/memory_engine/engine.pynow appendssupersedes:<id>relationships when refreshed inferred memories replace older ones.
- Added provenance marker enrichment for inferred preference memories:
src/memory_engine/personalization/adaptive.py- writes
inferred:true,inference_type:feedback_preference_shift, and signature relationship.
- Updated developer docs with retrieve response snippet showing provenance object:
docs/developer_documentation.md
Tests added/updated:
tests/unit/test_orbit_api_service.pytest_service_adds_inference_provenance_for_inferred_memoriestest_service_adds_inference_provenance_defaults_for_regular_memories
Validation:
python -m pytest -q: PASSpython -m ruff check src/orbit_api/service.py src/memory_engine/engine.py src/memory_engine/personalization/adaptive.py tests/unit/test_orbit_api_service.py: PASSpython -m pylint src/orbit_api/service.py tests/unit/test_orbit_api_service.py --fail-under=9.0: PASS (9.87/10)
Completed:
- Added account-level partitioning to memory persistence:
src/memory_engine/storage/db.pysrc/decision_engine/models.pymigrations/versions/20260221_0001_create_memories_table.pymigrations/versions/20260224_0003_add_account_key_to_memories.py
- Propagated
account_keythrough storage interfaces and implementations:src/decision_engine/storage_protocol.pysrc/decision_engine/storage_manager.pysrc/decision_engine/storage_sqlalchemy.py
- Scoped memory access paths end-to-end in engine + API service:
src/memory_engine/engine.pysrc/memory_engine/personalization/adaptive.pysrc/memory_engine/stage3_learning/loop.pysrc/memory_engine/storage/retrieval.pysrc/orbit_api/service.pysrc/orbit_api/app.py
- Enforced tenant boundaries in tests:
tests/integration/test_orbit_api_integration.pytests/unit/test_orbit_api_service.pytests/integration/test_orbit_api_errors.py(updated for strict tenant scope + quota behavior)tests/unit/test_storage_db.py
Validation:
python -m pytest tests/unit/test_orbit_api_service.py tests/integration/test_orbit_api_integration.py tests/integration/test_orbit_api_errors.py tests/unit/test_storage_db.py tests/unit/test_storage_sqlalchemy_manager.py tests/integration/test_adaptive_personalization.py tests/integration/test_engine_flow.py tests/unit/test_retrieval_service.py tests/unit/test_storage.py -q: PASSpython -m ruff check <changed .py files>: PASSpython -m alembic upgrade headagainst temp SQLite DB: PASS (verifiedmemories.account_key+ix_memories_account_key)
Completed:
- Added Cloud Build pipeline for image build/push/deploy:
cloudbuild.yaml
- Added reusable Cloud Run deploy script:
scripts/deploy_gcp_cloud_run.sh- supports:
- secret-injected
MDE_DATABASE_URLandORBIT_JWT_SECRET - optional Cloud SQL instance attach
- runtime env controls for quotas/auth/CORS/OTEL
- secret-injected
- Added GCP deployment docs + env matrix:
docs/DEPLOY_GCP_CLOUD_RUN.mddocs/GCP_ENV_MATRIX.md- linked from:
docs/deployment.mddocs/index.mdREADME.md
- Added initial Orbit Cloud dashboard/API-key management plan:
docs/ORBIT_CLOUD_DASHBOARD_PLAN.md
Validation:
bash -n scripts/deploy_gcp_cloud_run.sh: PASS
Completed:
- Added dashboard/account auth mapping and audit storage primitives:
src/memory_engine/storage/db.py- new tables:
api_dashboard_users,api_audit_logs api_keys.last_used_source
- new tables:
migrations/versions/20260224_0005_dashboard_auth_audit_and_key_rotation.py
- Added config knobs for stricter dashboard key endpoint rate limits + auto provisioning:
src/orbit_api/config.pydashboard_key_per_minute_limit(ORBIT_DASHBOARD_KEY_RATE_LIMIT_PER_MINUTE)dashboard_auto_provision_accounts(ORBIT_DASHBOARD_AUTO_PROVISION_ACCOUNTS)
- Hardened service layer:
src/orbit_api/service.py- JWT user -> account mapping with persisted identity binding
- audit trail events for key issue/revoke/rotate/authentication
- key rotation API (
rotate_api_key) - key listing pagination (
limit/cursor,has_more) - last-used source capture on API-key auth
- Hardened API layer:
src/orbit_api/app.py- strict scope dependencies for read/write/feedback/keys access
- dashboard endpoints on stricter rate limit bucket
- new endpoint:
POST /v1/dashboard/keys/{key_id}/rotate - dashboard key list pagination query params
- JWT auth flow resolves mapped account context before request handling
- Expanded API models:
src/orbit/models.pyApiKeyRotateRequest,ApiKeyRotateResponseApiKeyListResponse.cursor/has_moreApiKeySummary.last_used_source
Tests added/updated:
tests/unit/test_orbit_api_service.py- rotation behavior
- paginated key listing
- account mapping safety
tests/integration/test_orbit_api_integration.py- dashboard key pagination + rotation + old/new key behavior
- claim-based shared account mapping across users
tests/integration/test_orbit_api_errors.py- scope enforcement failures
- account-claim alignment in idempotency feedback path
Validation:
pytest: PASS (130 passed)ruff check: PASSpylint src/orbit_api/app.py src/orbit_api/service.py src/orbit_api/config.py src/orbit/models.py src/memory_engine/storage/db.py: PASS threshold (9.93/10)
Completed:
- Added browser dashboard API client + auth token-source wiring:
front-end/lib/orbit-dashboard.ts- supports:
NEXT_PUBLIC_ORBIT_API_BASE_URLNEXT_PUBLIC_ORBIT_DASHBOARD_TOKEN_SOURCE(localStorageorenv)- optional
NEXT_PUBLIC_ORBIT_DASHBOARD_BEARER_TOKEN
- typed methods for:
- create key
- list keys (paginated)
- revoke key
- rotate key
- Implemented full dashboard UI route:
front-end/app/dashboard/page.tsxfront-end/components/orbit/dashboard-console.tsx- includes:
- token apply/clear flow
- key table with pagination
- create/revoke/rotate dialogs
- copy-once secret reveal flow after create/rotate
- inline success/error status feedback
- Wired dashboard discoverability:
front-end/components/orbit/nav.tsxfront-end/components/orbit/hero.tsxfront-end/components/orbit/docs-sidebar.tsxfront-end/app/docs/page.tsx
- Added frontend env templates + deployment notes:
front-end/.env.examplefront-end/README.md- updated docs:
front-end/app/docs/deployment/page.tsxfront-end/app/docs/configuration/page.tsxfront-end/app/docs/api-reference/page.tsxfront-end/app/docs/rest-endpoints/page.tsxfront-end/app/docs/installation/page.tsx
Validation:
cd front-end && npm run build: PASScd front-end && npm run lint: blocked (no ESLint flat config present in repo; command fails before linting code)
Completed:
- Replaced browser-held dashboard bearer flow with server-only proxy auth:
front-end/lib/orbit-dashboard.ts- browser client now calls only
/api/dashboard/* - removed client token-source usage
- browser client now calls only
- Added server-side dashboard session auth primitives:
front-end/lib/dashboard-auth.ts- password mode / disabled mode
- signed HTTP-only session cookie
- strict session verification guard for proxy routes
- Added dashboard auth endpoints:
GET /api/dashboard/auth/sessionPOST /api/dashboard/auth/loginPOST /api/dashboard/auth/logout- files:
front-end/app/api/dashboard/auth/session/route.tsfront-end/app/api/dashboard/auth/login/route.tsfront-end/app/api/dashboard/auth/logout/route.ts
- Guarded all dashboard key proxy endpoints behind server-side session checks:
front-end/app/api/dashboard/keys/route.tsfront-end/app/api/dashboard/keys/[keyId]/revoke/route.tsfront-end/app/api/dashboard/keys/[keyId]/rotate/route.ts
- Updated dashboard UI for production-safe login/logout and expired-session handling:
front-end/components/orbit/dashboard-console.tsx
- Updated frontend env/docs for Vercel/server-only auth model:
front-end/.env.examplefront-end/README.mdfront-end/app/docs/configuration/page.tsxfront-end/app/docs/deployment/page.tsxfront-end/app/docs/troubleshooting/page.tsx
Validation:
cd front-end && npm run build: PASScd front-end && npx tsc --noEmit: PASScd front-end && npm run lint: blocked (no ESLint flat config present in repo)
Completed:
- Added OIDC auth mode and callback flow for dashboard sessions:
front-end/app/api/dashboard/auth/oidc/start/route.tsfront-end/app/api/dashboard/auth/oidc/callback/route.tsfront-end/lib/dashboard-auth.ts(OIDC discovery, token exchange, user claim resolution)
- Implemented tenant-aware short-lived JWT exchange in proxy:
front-end/lib/dashboard-auth.ts- per-session principal -> short-lived Orbit JWT (
account_keyderived deterministically) - configurable issuer/audience/ttl/algorithm
- per-session principal -> short-lived Orbit JWT (
front-end/lib/orbit-dashboard-proxy.ts- route-level required scope propagation (
keys:read/keys:write)
- route-level required scope propagation (
- Added strict proxy hardening controls:
- CSRF-style origin checks on dashboard mutation routes
- password login throttling + lockout window
- structured auth/proxy audit logs (
dashboard_login_failure,dashboard_login_locked, OIDC events, proxy action events)
- Updated dashboard API routes to enforce new controls/scopes:
front-end/app/api/dashboard/keys/route.tsfront-end/app/api/dashboard/keys/[keyId]/revoke/route.tsfront-end/app/api/dashboard/keys/[keyId]/rotate/route.tsfront-end/app/api/dashboard/auth/login/route.tsfront-end/app/api/dashboard/auth/logout/route.tsfront-end/app/api/dashboard/auth/session/route.ts
- Updated dashboard UI to support
password | oidc | disabled:front-end/components/orbit/dashboard-console.tsx- handles OIDC redirect path + auth callback error surface
- Added Playwright E2E harness and key auth scenarios:
front-end/playwright.config.tsfront-end/tests/e2e/dashboard-auth.spec.ts
- Added API-side metrics and alerting for hard runtime monitoring:
src/orbit_api/app.py(HTTP status observation middleware + dashboard auth failure counting)src/orbit_api/service.py(new counters: HTTP status totals, dashboard auth failures, key-rotation failures)deploy/prometheus/alerts-orbit.ymldeploy/prometheus/prometheus.yml(rule file loading)docker-compose.yml(alert rules mount)- docs updates:
docs/deployment.mddocs/index.mdfront-end/.env.examplefront-end/README.mdfront-end/app/docs/configuration/page.tsxfront-end/app/docs/deployment/page.tsxfront-end/app/docs/troubleshooting/page.tsx
Tests/validation:
python -m pytest tests/unit/test_orbit_api_service.py tests/integration/test_orbit_api_integration.py -q: PASSpython -m ruff check src/orbit_api/app.py src/orbit_api/service.py tests/unit/test_orbit_api_service.py tests/integration/test_orbit_api_integration.py: PASScd front-end && npm run build: PASScd front-end && npx tsc --noEmit: PASScd front-end && npm run lint: blocked (no ESLint flat config present in repo)cd front-end && npm install: failed in current local environment due upstream npm dependency-tree issue (Cannot read properties of null (reading 'edgesOut')); app build/typecheck unaffected.