Skip to content

feat: implement envelope operation logging with cursor pagination#764

Merged
coodos merged 4 commits intomainfrom
feat/logs-endpoint
Feb 4, 2026
Merged

feat: implement envelope operation logging with cursor pagination#764
coodos merged 4 commits intomainfrom
feat/logs-endpoint

Conversation

@coodos
Copy link
Contributor

@coodos coodos commented Feb 4, 2026

Description of change

Issue Number

Type of change

  • New (a change which implements a new feature)

How the change has been tested

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Summary by CodeRabbit

  • New Features

    • Envelope operations (create, update, delete, value updates) are logged with operation, platform, timestamp, ontology and envelope hash; logs can be appended and queried with cursor-based pagination via a new /logs HTTP endpoint.
  • Chores

    • One-time index creation and backfill steps added to initialization to populate and index operation logs.
  • Documentation

    • API docs updated with /logs endpoint, parameters and examples.
  • Tests

    • Integration and end-to-end tests covering logging, pagination and header validation.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 4, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds envelope operation logging: new DB types, DbService methods for appending and paginating logs, a /logs HTTP endpoint, GraphQL mutation hooks to emit logs (best-effort), migrations (index + backfill) run at startup/tests, and unit + e2e tests for storage and retrieval.

Changes

Cohort / File(s) Summary
Type Definitions
infrastructure/evault-core/src/core/db/types.ts
Add types for operation logs: EnvelopeOperationType, EnvelopeOperationLogEntry, AppendEnvelopeOperationLogParams, GetEnvelopeOperationLogsResult.
Database Service & Tests
infrastructure/evault-core/src/core/db/db.service.ts, infrastructure/evault-core/src/core/db/db.service.spec.ts
Add methods getMetaEnvelopeIdByEnvelopeId, appendEnvelopeOperationLog, getEnvelopeOperationLogs (cursor-based pagination, limit bounds); tests for storing, pagination, and meta-envelope mapping.
Hashing & Ontology Helpers
infrastructure/evault-core/src/core/db/envelope-hash.ts, infrastructure/evault-core/src/core/db/ontology-platform.ts, .../ontology-platform.spec.ts
Add deterministic envelope hash utilities and ontology→platform inference used by backfill; unit tests for inference.
Migrations / Backfill
infrastructure/evault-core/src/core/db/migrations/add-envelope-operation-log-index.ts, infrastructure/evault-core/src/core/db/migrations/backfill-envelope-operation-logs.ts
Add migration to create EnvelopeOperationLog indexes and a backfill script to create initial log entries from existing MetaEnvelope nodes; marker node to avoid rerun.
HTTP Server & Docs
infrastructure/evault-core/src/core/http/server.ts, docs/docs/Infrastructure/eVault.md
New GET /logs endpoint requiring X-ENAME, supports limit and cursor, returns { logs, nextCursor, hasMore }; Swagger/docs updated.
GraphQL Instrumentation
infrastructure/evault-core/src/protocol/graphql-server.ts
Fire-and-forget logging after create/update/delete/update_envelope_value mutations: compute envelopeHash, look up meta info when needed, call appendEnvelopeOperationLog (errors caught and logged).
Startup & Test Setup
infrastructure/evault-core/src/index.ts, infrastructure/evault-core/src/test-utils/e2e-setup.ts
Run index-creation and backfill modules during initialization and E2E setup via dynamic imports; wrapped in try/catch with warnings.
E2E Tests
infrastructure/evault-core/src/e2e/evault-core.e2e.spec.ts
Add E2E tests for GET /logs (success after storing meta-envelope; 400 when X-ENAME missing).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant GraphQL as GraphQL Server
    participant HTTP as HTTP Server
    participant DbService
    participant DB as Neo4j

    Client->>GraphQL: mutation (create/update/delete/update_envelope_value)
    GraphQL->>DB: persist envelope change
    GraphQL->>GraphQL: compute envelopeHash / lookup metaEnvelopeId & ontology
    GraphQL->>DbService: appendEnvelopeOperationLog(params) (fire-and-forget)
    DbService->>DB: CREATE EnvelopeOperationLog node

    Client->>HTTP: GET /logs (X-ENAME, limit, cursor)
    HTTP->>DbService: getEnvelopeOperationLogs(eName, {limit, cursor})
    DbService->>DB: MATCH logs ORDER BY timestamp DESC, id ASC WITH cursor filter
    DB-->>DbService: paginated records
    DbService-->>HTTP: { logs, nextCursor, hasMore }
    HTTP-->>Client: 200 { logs, nextCursor, hasMore }
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

evault-refactor

Suggested reviewers

  • sosweetham
  • xPathin
  • dkraemerwork

Poem

🐰 I hop through logs with a tiny pen,
I hash the envelopes and write them when,
Cursors curl like carrot vines,
Paging through timestamps in neat lines. 🥕📜

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description follows the template structure but lacks critical implementation details; it contains no issue number, no explanation of the feature being added, and no description of how testing was performed. Complete the PR description with the linked issue number, a detailed explanation of the envelope operation logs feature, and specific testing approach or scenarios covered.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main feature added: envelope operation logging with cursor pagination.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/logs-endpoint

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Fix all issues with AI agents
In `@infrastructure/evault-core/src/core/db/db.service.ts`:
- Around line 978-1007: The cursor comparison in the cypher used by
runQueryInternal for EnvelopeOperationLog is inconsistent with the ORDER BY
clause: with "ORDER BY l.timestamp DESC, l.id ASC" the cursor predicate
"(l.timestamp < $cursorTs) OR (l.timestamp = $cursorTs AND l.id < $cursorId)" is
wrong and should use l.id > $cursorId for correct pagination; update the query
string to use "l.id > $cursorId" in the cursor branch (and keep the same
parameter names cursorTs/cursorId and limitPlusOne) so results for equal
timestamps are correctly ordered and no items are skipped or duplicated.

In `@infrastructure/evault-core/src/core/protocol/graphql-server.ts`:
- Around line 7-10: The import of computeEnvelopeHash and
computeEnvelopeHashForDelete in graphql-server.ts fails because
../db/envelope-hash does not exist or exports differ; either restore/create the
module exporting those two functions or correct the import to the actual module
that provides them (e.g., update the path or named exports to match where
computeEnvelopeHash and computeEnvelopeHashForDelete are defined), then run the
build to verify the import resolves.
- Around line 244-260: The post-write call to appendEnvelopeOperationLog (which
uses computeEnvelopeHash and result.metaEnvelope.id) must not cause the mutation
to fail if logging errors; change the logic so the main write completes
atomically and the log is recorded best-effort—either include the envelope log
in the same DB transaction as the write (so both commit or both rollback) or, if
a transaction is not feasible, invoke appendEnvelopeOperationLog without
blocking the response and wrap it in a try/catch (or attach .catch) to
swallow/log errors; update the code paths that call appendEnvelopeOperationLog
(e.g., in the create mutation where result.metaEnvelope is used) so failures in
appendEnvelopeOperationLog never bubble up and cause duplicate side effects.
- Around line 349-363: The audit log is being appended before the actual
deletion, and meta may be null; move logging to occur only after confirming
deletion succeeds (or perform both actions inside a DB transaction).
Specifically: call findMetaEnvelopeById(id, context.eName) to capture ontology
first, then call deleteMetaEnvelope(id, context.eName) and verify its
success/return value, and only then call appendEnvelopeOperationLog with
computeEnvelopeHashForDelete(id), platform, timestamp and ontology (use
null/explicit fallback if meta is missing). Alternatively wrap
deleteMetaEnvelope and appendEnvelopeOperationLog in a transaction to ensure
atomicity.
- Around line 379-405: Create the missing module ../db/envelope-hash that
exports computeEnvelopeHash and computeEnvelopeHashForDelete, implement
deterministic hashing of the provided envelope inputs (e.g., ontology and
payload) and ensure the functions are used where computeEnvelopeHash is called
in graphql-server.ts; specifically, make computeEnvelopeHash include an id field
in the payload for the "update_envelope_value" operation (use the envelopeId
parameter as id) so its inputs match the create/update hash shape, and implement
computeEnvelopeHashForDelete to accept the same identifying fields used when
deleting; ensure exports match the named imports used by graphql-server.ts.

In `@infrastructure/evault-core/src/e2e/evault-core.e2e.spec.ts`:
- Around line 600-630: The test uses the variable client inside the "GET /logs
endpoint" block but never initializes it; add a beforeAll (and matching afterAll
if needed) in that describe block to set up client the same way other suites do
(e.g., call whatever setup used elsewhere to assign client and ensure evault1 is
available), so that client.storeMetaEnvelope and subsequent fetch calls run
against a valid client instance; reference the describe block name "GET /logs
endpoint", the variable client, and the method storeMetaEnvelope to locate where
to add the beforeAll/afterAll setup and teardown.

In `@infrastructure/evault-core/src/index.ts`:
- Around line 120-126: The dynamic import/usage of backfillEnvelopeOperationLogs
in index.ts is referencing a missing migration module and will fail at runtime;
either add an exported async function backfillEnvelopeOperationLogs that accepts
the existing driver and performs the backfill, and place it where the dynamic
import in index.ts expects to load it, or remove the try/catch block and call
entirely (including the import and await backfillEnvelopeOperationLogs(driver))
if the migration isn’t needed yet—ensure the symbol name
backfillEnvelopeOperationLogs and the driver argument remain consistent with the
current code when you implement or remove the call.

@coodos coodos force-pushed the feat/logs-endpoint branch from 1b7566b to 11e220c Compare February 4, 2026 07:23
@coodos coodos force-pushed the feat/logs-endpoint branch from bf4e3ab to 36b46c7 Compare February 4, 2026 07:34
@coodos coodos changed the title feat: logs eat: implement envelope operation logging with cursor pagination Feb 4, 2026
@coodos coodos changed the title eat: implement envelope operation logging with cursor pagination feat: implement envelope operation logging with cursor pagination Feb 4, 2026
@coodos coodos merged commit 570a770 into main Feb 4, 2026
5 of 6 checks passed
@coodos coodos deleted the feat/logs-endpoint branch February 4, 2026 08:11
This was referenced Feb 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants