Skip to content

SF-19-in-memory-singleton-for-config-data#12

Merged
djradon merged 20 commits intomainfrom
SF-19-in-memory-singleton-for-config-data
Aug 5, 2025
Merged

SF-19-in-memory-singleton-for-config-data#12
djradon merged 20 commits intomainfrom
SF-19-in-memory-singleton-for-config-data

Conversation

@djradon
Copy link
Contributor

@djradon djradon commented Aug 2, 2025

@CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive, structured logging and error handling system with support for console, file, and Sentry logging, including context-rich log messages and error reporting.
    • Added utilities and configuration for managing service URIs, mesh registries, and dynamic service configuration using Quadstore-backed graphs.
    • Enhanced service configuration with expanded type definitions, dynamic context generation, and improved validation.
    • Added new endpoints and utilities for mesh and node operations, with improved logging and error context.
  • Bug Fixes

    • Improved error handling and logging across routes and service initialization to provide clearer diagnostics and stability.
  • Documentation

    • Added detailed documentation for error handling and logging usage, including best practices and integration examples.
  • Refactor

    • Modularized configuration, logging, and error handling code for better maintainability and clarity.
    • Updated naming conventions and type structures for configuration and node management.
  • Style

    • Standardized JSON and TypeScript formatting to use double quotes and consistent key/value styles.
  • Tests

    • Added and updated unit and integration tests for logging, error handling, Quadstore utilities, and configuration management.
  • Chores

    • Updated configuration and ignore files, introduced new dependencies, and improved development tooling.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 2, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This update introduces a comprehensive overhaul of the logging, error handling, and configuration systems in the flow-service and flow-core modules. It adds a new structured, multi-channel logging framework with support for file and Sentry logging, enhanced error handling with contextual metadata, and a modularized configuration system leveraging Quadstore for graph-based config storage and merging. Numerous new utilities, types, and test suites are introduced, while legacy logger and test scripts are removed or replaced.

Changes

Cohort / File(s) Change Summary
Structured Logging & Error Handling (Core)
flow-core/src/utils/logger/types.ts, flow-core/src/utils/logger/formatters.ts, flow-core/src/utils/logger/structured-logger.ts, flow-core/src/utils/logger/file-logger.ts, flow-core/src/utils/logger/sentry-logger.ts, flow-core/src/utils/logger/error-handlers.ts, flow-core/src/utils/logger/index.ts
Introduces a robust, extensible structured logging system with support for console, file, and Sentry logging. Adds detailed log context types, message formatting, file rotation, Sentry integration, and enhanced error handling with contextual metadata.
Logging System Integration (Service)
flow-service/src/utils/service-logger.ts, flow-service/src/utils/errors.ts, flow-service/src/utils/service-log-context.ts, flow-service/src/routes/health.ts, flow-service/src/routes/meshes.ts, flow-service/src/routes/weave.ts, flow-service/src/utils/mesh-utils.ts, flow-service/src/utils/startup-logger.ts, flow-service/src/services/metadata-composer.ts, flow-service/src/config/loaders/env-loader.ts, flow-service/src/config/loaders/jsonld-loader.ts, flow-service/src/config/index.ts, flow-service/src/config/resolution/service-config-resolver.ts, flow-service/src/config/defaults.ts, flow-service/src/config/config-types.ts, flow-service/src/config/loaders/quadstore-loader.ts, flow-service/src/config/resolution/service-config-accessor.ts, flow-service/src/config/resolution/service-config-validator.ts, flow-service/src/utils/service-uri-builder.ts, flow-service/src/service-constants.ts
Refactors the service to use the new structured logger and error handler. Introduces service-specific logger configuration, context factories, and log context helpers. Updates all service modules, routes, and config loaders to use the new logging and error handling interfaces.
Quadstore Utilities & Integration
flow-core/src/utils/quadstore/quadstore-utils.ts, flow-core/src/utils/quadstore/quadstore-factory.ts, flow-core/src/utils/rdfjs-utils.ts, flow-core/src/types.ts, flow-core/src/deps.ts, flow-core/src/platform-constants.ts, flow-core/src/quadstore-default-bundle.ts, flow-service/src/quadstore-default-bundle.ts
Adds utility modules for managing RDF quadstore graphs, JSON-LD conversion, and in-memory quadstore bundles. Introduces new types and constants for log levels and quadstore bundling.
Configuration System Overhaul
flow-service/src/config/index.ts, flow-service/src/config/defaults.ts, flow-service/src/config/config-types.ts, flow-service/src/config/loaders/env-loader.ts, flow-service/src/config/loaders/jsonld-loader.ts, flow-service/src/config/loaders/quadstore-loader.ts, flow-service/src/config/resolution/service-config-resolver.ts, flow-service/src/config/resolution/service-config-accessor.ts, flow-service/src/config/resolution/service-config-validator.ts, flow-service/src/config/node-config.default.jsonld, flow-service/flow-service-config.jsonld
Refactors the configuration system to use Quadstore-backed named graphs, modularizes config types, loaders, and accessors, and updates JSON-LD config files and context handling.
Testing: Logging & Error Handling
flow-core/tests/integration/logger/logger.test.ts, flow-core/tests/integration/logger/formatters.test.ts, flow-core/tests/integration/logger/error-handlers.test.ts, flow-service/tests/integration/logging/logger.test.ts, flow-service/tests/integration/logging/formatting-direct.test.ts, flow-service/tests/integration/logging/pretty-format-simple.test.ts, flow-service/tests/integration/logging/handle-caught-error.test.ts, flow-service/tests/integration/logging/log-retention-config.test.ts, flow-service/tests/integration/logging/sentry-init.test.ts, flow-service/tests/integration/logging/sentry-logging.test.ts
Adds and updates integration tests for logging, error formatting, file logging, Sentry integration, and error handling. Some tests are placeholders or have been updated to use the new logger.
Testing: Quadstore Utilities
flow-core/tests/unit/quadstore-utils.test.ts, flow-service/tests/integration/quadstore-utils.test.ts, flow-service/tests/integration/quadstore-accessor.test.ts
Adds unit and integration tests for quadstore graph utilities, SPARQL queries, and graph manipulation.
Documentation & Guidance
flow-core/docs/error-handling-usage.md, .ai-guidance.md
Adds comprehensive documentation for the new error handling system and updates AI guidance for code practices.
Removed Legacy Logger & Tests
flow-service/src/utils/logger.ts, flow-service/tests/integration/test-log-retention-config.ts, flow-service/tests/integration/test-sentry-init.ts, flow-service/tests/integration/test-sentry-logging.ts
Removes the legacy logger implementation and old test scripts for log retention and Sentry integration.
Config & Linting Tooling
eslint.config.mjs, deno.json, flow-service/deno.json, .gitignore, package.json
Adds ESLint configuration for TypeScript, updates Deno and gitignore settings, and introduces a package.json with dependencies for linting and quadstore.

Sequence Diagram(s)

sequenceDiagram
    participant ServiceModule as Service Module (e.g., Route, Config)
    participant Logger as StructuredLogger
    participant FileLogger as FileLogger
    participant Sentry as Sentry
    participant ErrorHandler as Error Handler

    ServiceModule->>Logger: log(level, message, context)
    Logger->>FileLogger: writeToFile(formattedLog)
    Logger->>Sentry: reportErrorToSentry(error, level, context)
    ServiceModule->>ErrorHandler: handleCaughtError(error, message, context)
    ErrorHandler->>Logger: error(level, message, context)
    ErrorHandler->>Sentry: reportErrorToSentry(error, level, context)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90+ minutes

  • Complexity: The changes span core architecture, logging, error handling, configuration, and testing, with many new modules, significant refactoring, and replacement of foundational utilities.
  • Scope: Dozens of new files, removals, and rewrites across both flow-core and flow-service.
  • Review Time: Expect at least 1.5 hours for a thorough review, focusing on architecture, correctness, and contract compatibility.

Poem

🐇
Logs now sparkle, errors sing,
Context flows in everything.
Sentry watches, files spin tight,
Quads and graphs now work just right.
Rabbits hop through code anew—
Structured logs for every view!
📝✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5046780 and 87f16b1.

📒 Files selected for processing (5)
  • flow-core/src/utils/quadstore/quadstore-utils.ts (1 hunks)
  • flow-core/tests/unit/quadstore-utils.test.ts (1 hunks)
  • flow-service/src/config/loaders/quadstore-loader.ts (1 hunks)
  • flow-service/tests/integration/quadstore-accessor.test.ts (1 hunks)
  • flow-service/tests/integration/quadstore-utils.test.ts (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch SF-19-in-memory-singleton-for-config-data

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 18

🔭 Outside diff range comments (3)
flow-service/tests/integration/logging/sentry-logging.test.ts (1)

1-7: Placeholder test will currently break no-unused-locals / no-unused-vars lint rules

Both logger and config are imported but never used.
If tsconfig.json has noUnusedLocals (common in this repo) the test suite will not compile.

Two quick fixes:

-import { logger } from '../../../src/utils/logger.ts';
-import { singletonServiceConfigAccessor as config } from '../../../src/config/resolution/service-config-accessor.ts';
+// TODO: remove once the first assertions are added
+// import { logger } from '../../../src/utils/logger.ts';
+// import { singletonServiceConfigAccessor as config } from '../../../src/config/resolution/service-config-accessor.ts';

…or stub a minimal test:

Deno.test('sentry-logging – placeholder', () => {
  logger.info('placeholder'); // prevents unused-import error
});

Until real assertions land, consider Deno.test({ name, ignore: true, fn }) to keep CI green.

flow-service/tests/integration/logging/log-retention-config.test.ts (1)

1-6: Imports are unused and the file contains no Deno.test blocks

This will fail under noUnusedLocals / noUnusedVars.
Either mark the file as ignored for now or add a stub test that at least exercises loadEnvConfig so the imports are used.

flow-service/src/services/metadata-composer.ts (1)

25-26: Replace synchronous config property access with async getters

The ServiceConfigAccessor only exposes async methods (getPort(), getHost(), getMeshPaths()), so config.defaultAttributedTo and config.defaultDelegationChain will always be undefined. You should either:

  • Implement async getters in ServiceConfigAccessor for defaultAttributedTo and defaultDelegationChain that run the appropriate SPARQL queries, e.g.:

    async getDefaultAttributedTo(): Promise<AttributedTo | undefined> {  }
    async getDefaultDelegationChain(): Promise<DelegationChain | undefined> {  }
  • Or load those values from a synchronous source before composing metadata.

Then update composeMetadataContent to be async and use:

- const attributedTo = config.defaultAttributedTo;
- const delegationChain = config.defaultDelegationChain;
+ const attributedTo = await config.getDefaultAttributedTo();
+ const delegationChain = await config.getDefaultDelegationChain();

Files to update:

  • flow-service/src/config/resolution/service-config-accessor.ts – add the two async getters.
  • flow-service/src/services/metadata-composer.ts – make composeMetadataContent async and replace the two property accesses with await calls.
♻️ Duplicate comments (1)
flow-service/tests/integration/logging/sentry-init.test.ts (1)

1-8: Same unused-import issue as the previous file

initSentry, logger, and config are imported but never referenced.
Apply one of the mitigation approaches described in the previous comment to avoid TypeScript compile failures in CI.

🧹 Nitpick comments (28)
.gitignore (1)

12-12: Consider using a directory-specific ignore pattern

logs will ignore both a sibling file called logs and any directory named logs at any depth.
If the intent is only to ignore the directory, a trailing slash makes that explicit and avoids accidental skips of legitimately-named files:

-logs
+logs/
package.json (1)

1-5: Add the corresponding ESLint plugin for TypeScript rules

Only the parser is listed; most TS-specific rules live in @typescript-eslint/eslint-plugin.
Without it, your config will warn that rules are unknown or silently do nothing.

   "devDependencies": {
     "@typescript-eslint/parser": "^8.38.0",
+    "@typescript-eslint/eslint-plugin": "^8.38.0",
     "eslint": "^9.32.0"
   }

Ensure eslint.config.mjs (or equivalent) extends the plugin to activate the rules.

.ai-guidance.md (1)

17-20: Minor wording/grammar tweak for clarity

“Too-long files are cause syntax errors” reads awkwardly. Suggested rephrase:

-So important! Too-long files are cause syntax errors from agent edits.
+So important! Overly long files often trigger syntax errors during automated agent edits.
deno.json (1)

14-16: Task whitelist looks correct but double-space after --allow-read is harmless

Nothing functionally wrong; feel free to trim the extra space next time.

flow-service/tests/integration/logging/handle-caught-error.test.ts (2)

8-15: Deep relative import paths are brittle – recommend using the import-map

You’ve updated the paths to ../../../src/..., which works today but will break on the next directory move.
Since Deno already supports import maps (and this repo ships one for @deps/*), add an entry:

{
  "imports": {
    "@flow/logger": "./src/utils/logger.ts",
    "@flow/errors": "./src/utils/errors.ts",
    "@flow/config-types": "./src/config/config-types.ts"
  }
}

Then the imports become:

import { handleCaughtError } from '@flow/logger';
import { ConfigurationError, FlowServiceError, ValidationError } from '@flow/errors';
import { ConfigValidationError } from '@flow/config-types';

Result: shorter lines, no ../../../ gymnastics, and easier refactors.


90-100: Minor nit – test numbering skips 9

Lines 90-100 label the section “Test 10”, but there is no “Test 9”.
Won’t break anything, yet can confuse readers scanning logs.

flow-service/src/utils/logger.ts (1)

221-259: Exporting formatConsoleMessage is 👍 but mind ANSI padding

  1. prefix already right-pads the raw level.
    Inside the isDevelopment branch you do coloredLevel.padEnd(5) again, but the escape codes inflate the length, so the visual width is off.
    Consider padding before coloring:
-const coloredLevel = level === 'ERROR' || level === 'CRITICAL'
-  ? colorize('red', level)
+const rawPaddedLevel = level.padEnd(5);
+const coloredLevel = level === 'ERROR' || level === 'CRITICAL'
+  ? colorize('red', rawPaddedLevel)
   : …;
-const coloredPrefix = colorize('gray', `[${timestamp}]`) +
-  ` ${coloredLevel.padEnd(5)}`;
+const coloredPrefix = colorize('gray', `[${timestamp}]`) +
+  ` ${coloredLevel}`;
  1. The function is now public – please add a short JSDoc to make its intended, internal-only audience explicit and discourage external callers from bypassing logger.
flow-service/src/quadstore-default-bundle.ts (1)

4-11: Consider using the factory function to reduce code duplication.

This code duplicates the logic from createQuadstoreBundle in quadstore-factory.ts. Consider using the factory function for consistency and maintainability.

-const backend = new MemoryLevel();
-const df = new DataFactory();
-const store = new Quadstore({ backend, dataFactory: df });
-const engine = new Engine(store);
-
-await store.open();
-
-export const defaultQuadstoreBundle: QuadstoreBundle = { store, df, backend, engine };
+import { createQuadstoreBundle } from '../../flow-core/src/utils/quadstore/quadstore-factory.ts';
+
+export const defaultQuadstoreBundle: QuadstoreBundle = await createQuadstoreBundle();
flow-core/src/types.ts (1)

7-8: Consider adding JSDoc documentation.

Adding JSDoc comments would improve the interface documentation and developer experience.

-// Quadstore Bundle Type
+/**
+ * A bundle containing all the necessary components for a Quadstore setup.
+ * @template B - The backend type, extending AbstractLevel
+ */
 export interface QuadstoreBundle<B extends AbstractLevel<any, any, any> = AbstractLevel<any, any, any>> {
flow-service/tests/integration/quadstore-accessor.test.ts (2)

37-37: Consider adding null check instead of non-null assertion.

The non-null assertion operator (!) assumes the engine is always present, but it would be safer to add a proper null check for more robust error handling.

-  const bindingsStream = await engine!.queryBindings(query, { sources: [store] });
+  if (!engine) {
+    throw new Error("Query engine is not available");
+  }
+  const bindingsStream = await engine.queryBindings(query, { sources: [store] });

38-40: Improve type safety for bindings stream iteration.

The as any cast bypasses TypeScript's type checking. Consider using proper typing or adding runtime validation for the binding structure.

-  for await (const binding of bindingsStream as any) {
-    result.push(binding.get("o").value);
+  for await (const binding of bindingsStream) {
+    const objectBinding = binding.get("o");
+    if (objectBinding) {
+      result.push(objectBinding.value);
+    }
   }
flow-core/src/utils/rdfjs-utils.ts (1)

6-6: Consider making DataFactory configurable or reusable.

While creating a local DataFactory instance works, consider whether this should be configurable or if there's a shared instance that could be reused across the application to ensure consistency.

-const df = new DataFactory();
+// Consider making this configurable or using a shared instance
+const df = new DataFactory();
eslint.config.mjs (1)

15-15: Consider relaxing the quote-props rule.

The "quote-props": ["error", "always"] rule forces quotes on all object properties, even when not required (e.g., "foo" instead of foo). This can make code less readable. Consider using "as-needed" instead.

-      "quote-props": ["error", "always"],
+      "quote-props": ["error", "as-needed"],
flow-service/main.ts (1)

48-49: Consider caching frequently accessed configuration values

The host and port values are accessed multiple times during startup. Since these values don't change during runtime, consider caching them after the first access to avoid repeated async calls.

+// Cache frequently accessed config values after initialization
+const host = await singletonServiceConfigAccessor.getHost();
+const port = await singletonServiceConfigAccessor.getPort();
+
 servers: [
   {
-    url: `http://${await singletonServiceConfigAccessor.getHost()}:${await singletonServiceConfigAccessor.getPort()}`,
+    url: `http://${host}:${port}`,
     description: 'Configured server',
   },
 ],

 // ... later in the file
 Deno.serve({
-  port: await singletonServiceConfigAccessor.getPort(),
-  hostname: await singletonServiceConfigAccessor.getHost(),
+  port: port,
+  hostname: host,
 }, app.fetch);

Also applies to: 101-102

flow-service/src/config/resolution/service-config-validator.ts (1)

2-6: Consider extracting predicate URIs as constants

The hardcoded URIs should be defined as constants for better maintainability and consistency across the codebase.

Add these constants at the module level or import from a shared constants file:

const FSVC_NAMESPACE = 'https://semantic-flow.github.io/ontology/flow-service/';
const FSVC_PORT = `${FSVC_NAMESPACE}port`;
const FSVC_HOST = `${FSVC_NAMESPACE}host`;
flow-service/tests/integration/logging/formatting-direct.test.ts (1)

146-146: Update the year check in log validation

The hardcoded year check [2025- might fail in future years. Consider making it more flexible.

-  if (logContent.includes('[2025-') && !logContent.startsWith('{"timestamp"')) {
+  const currentYear = new Date().getFullYear();
+  if (logContent.includes(`[${currentYear}-`) && !logContent.startsWith('{"timestamp"')) {
flow-core/tests/unit/quadstore-utils.test.ts (1)

1-86: Consider extracting common test setup

Each test creates its own quadstore bundle. Consider extracting common setup to reduce duplication and improve test performance.

// Add at the top of the file
let testQuadstoreBundle: any;
let df: any;
let store: any;

// Setup before all tests
Deno.test({
  name: "quadstore-utils tests",
  fn: async (t) => {
    testQuadstoreBundle = await createQuadstoreBundle();
    df = testQuadstoreBundle.df;
    store = testQuadstoreBundle.store;
    
    await t.step("countQuadsInStream counts quads correctly", async () => {
      // ... existing test logic
    });
    
    // ... other test steps
  },
  sanitizeResources: false,
  sanitizeOps: false,
});
flow-service/tests/integration/quadstore-utils.test.ts (1)

52-55: Use the imported countQuadsInStream directly

The helper function countQuadsInGraph is just a thin wrapper that could be inlined to reduce code duplication.

Replace the helper function usage with direct calls:

-  let count = await countQuadsInGraph(graphA, store);
+  let count = await countQuadsInStream(store.match(undefined, undefined, undefined, graphA));

And remove the helper function definition at lines 52-55.

flow-service/src/utils/startup-logger.ts (1)

42-51: Track incomplete configuration migration

The TODOs indicate that the configuration migration is incomplete. Several config properties are hardcoded instead of being retrieved from the accessor.

Would you like me to help implement the missing configuration accessor methods or create a GitHub issue to track this technical debt?

flow-service/src/config/resolution/service-config-loader.ts (1)

14-14: Clarify or complete the TODO comment

The TODO comment "dct:conformsTo" is unclear and provides no context about what needs to be implemented.

Please provide more context about this TODO, or would you like me to help research what "dct:conformsTo" refers to in this context and create an issue to track it?

flow-service/src/config/resolution/service-config-accessor.ts (1)

7-85: Consider caching configuration values

Each config access triggers a SPARQL query. For frequently accessed values like host and port, this could impact performance.

Consider implementing a caching layer:

private cache = new Map<string, { value: any, timestamp: number }>();
private cacheTimeout = 60000; // 1 minute

private getCached<T>(key: string, fetcher: () => Promise<T>): Promise<T> {
  const cached = this.cache.get(key);
  if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
    return Promise.resolve(cached.value);
  }
  const value = await fetcher();
  this.cache.set(key, { value, timestamp: Date.now() });
  return value;
}
flow-service/src/config/resolution/service-config-resolver.ts (1)

51-53: Address TODO: Implement mesh node config loading.

The TODO comment indicates missing functionality for loading mesh root node configuration. This should be implemented to complete the configuration loading pipeline.

Would you like me to help implement the mesh node config loading logic or create an issue to track this task?

flow-service/src/config/config-types.ts (3)

60-72: Complete the TODO: Finalize interface naming.

The TODO comment indicates the MeshRootNodeConfig interface name might need to be changed. This should be resolved to maintain naming consistency.


88-91: Complete the AttributedTo interface definition.

The TODO comment indicates this interface needs a complete definition beyond just the @id property.

Would you like me to help define the complete AttributedTo interface based on the ontology or create an issue to track this?


31-36: Consider more compact formatting for the union type.

-  readonly 'fsvc:logRotationInterval'?:
-  | 'daily'
-  | 'weekly'
-  | 'monthly'
-  | 'size-based';
+  readonly 'fsvc:logRotationInterval'?: 'daily' | 'weekly' | 'monthly' | 'size-based';
flow-service/src/config/defaults.ts (2)

12-13: Address TODO: Make local context configurable

The TODO comment indicates that the local context should use the config host and port dynamically. This hardcoded http://localhost/graph/ might not work in all deployment scenarios.

Would you like me to help implement a solution that dynamically constructs the local context URL based on the service configuration?


23-24: Consider completing the rename indicated in TODO

The TODO suggests renaming this constant to better indicate its purpose for root MeshNodes. Consider renaming PLATFORM_NODE_DEFAULTS to something like PLATFORM_MESH_ROOT_NODE_DEFAULTS for clarity.

flow-service/src/config/index.ts (1)

11-18: Consider making graph URIs configurable

The CONFIG_GRAPH_NAMES contains hardcoded http://localhost/graph/ URLs. Similar to the local context in defaults.ts, these should ideally be configurable based on the service's host and port settings.

Consider implementing a function that generates these graph URIs dynamically based on the service configuration:

-export const CONFIG_GRAPH_NAMES = {
-  platformServiceDefaults: 'http://localhost/graph/platformServiceDefaults',
-  platformImplicitMeshRootNodeConfig: 'http://localhost/graph/platformImplicitMeshRootNodeConfig',
-  inputServiceConfig: 'http://localhost/graph/inputServiceConfig',
-  inputMeshRootNodeConfig: 'http://localhost/graph/inputMeshRootNodeConfig',
-  mergedServiceConfig: 'http://localhost/graph/mergedServiceConfig',
-  // Per-node effective configs could be stored with dynamic graph names
-};
+export function getConfigGraphNames(baseUrl: string = 'http://localhost/graph') {
+  return {
+    platformServiceDefaults: `${baseUrl}/platformServiceDefaults`,
+    platformImplicitMeshRootNodeConfig: `${baseUrl}/platformImplicitMeshRootNodeConfig`,
+    inputServiceConfig: `${baseUrl}/inputServiceConfig`,
+    inputMeshRootNodeConfig: `${baseUrl}/inputMeshRootNodeConfig`,
+    mergedServiceConfig: `${baseUrl}/mergedServiceConfig`,
+    // Per-node effective configs could be stored with dynamic graph names
+  };
+}
+
+export const CONFIG_GRAPH_NAMES = getConfigGraphNames();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e11155 and 0d67c44.

⛔ Files ignored due to path filters (4)
  • deno.lock is excluded by !**/*.lock
  • flow-service/deno.lock is excluded by !**/*.lock
  • flow-service/logs/test-pretty-direct.log is excluded by !**/*.log
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (45)
  • .ai-guidance.md (1 hunks)
  • .gitignore (1 hunks)
  • deno.json (1 hunks)
  • eslint.config.mjs (1 hunks)
  • flow-core/src/deps.ts (1 hunks)
  • flow-core/src/platform-constants.ts (1 hunks)
  • flow-core/src/types.ts (1 hunks)
  • flow-core/src/utils/quadstore-utils.ts (1 hunks)
  • flow-core/src/utils/quadstore/quadstore-factory.ts (1 hunks)
  • flow-core/src/utils/rdfjs-utils.ts (1 hunks)
  • flow-core/tests/unit/quadstore-utils.test.ts (1 hunks)
  • flow-service/deno.json (1 hunks)
  • flow-service/flow-service-config.jsonld (1 hunks)
  • flow-service/main.ts (5 hunks)
  • flow-service/src/config/config-types.ts (6 hunks)
  • flow-service/src/config/defaults.ts (2 hunks)
  • flow-service/src/config/index.ts (2 hunks)
  • flow-service/src/config/loaders/env-loader.ts (2 hunks)
  • flow-service/src/config/loaders/jsonld-loader.ts (7 hunks)
  • flow-service/src/config/loaders/quadstore-loader.ts (1 hunks)
  • flow-service/src/config/node-config.default.jsonld (1 hunks)
  • flow-service/src/config/resolution/service-config-accessor.ts (1 hunks)
  • flow-service/src/config/resolution/service-config-loader.ts (1 hunks)
  • flow-service/src/config/resolution/service-config-resolver.ts (1 hunks)
  • flow-service/src/config/resolution/service-config-validator.ts (1 hunks)
  • flow-service/src/quadstore-default-bundle.ts (1 hunks)
  • flow-service/src/routes/meshes.ts (2 hunks)
  • flow-service/src/routes/weave.ts (1 hunks)
  • flow-service/src/services/metadata-composer.ts (1 hunks)
  • flow-service/src/utils/logger.ts (1 hunks)
  • flow-service/src/utils/mesh-utils.ts (2 hunks)
  • flow-service/src/utils/startup-logger.ts (3 hunks)
  • flow-service/tests/integration/logging/formatting-direct.test.ts (3 hunks)
  • flow-service/tests/integration/logging/handle-caught-error.test.ts (1 hunks)
  • flow-service/tests/integration/logging/log-retention-config.test.ts (1 hunks)
  • flow-service/tests/integration/logging/logger.test.ts (1 hunks)
  • flow-service/tests/integration/logging/pretty-format-simple.test.ts (1 hunks)
  • flow-service/tests/integration/logging/sentry-init.test.ts (1 hunks)
  • flow-service/tests/integration/logging/sentry-logging.test.ts (1 hunks)
  • flow-service/tests/integration/quadstore-accessor.test.ts (1 hunks)
  • flow-service/tests/integration/quadstore-utils.test.ts (1 hunks)
  • flow-service/tests/integration/test-log-retention-config.ts (0 hunks)
  • flow-service/tests/integration/test-sentry-init.ts (0 hunks)
  • flow-service/tests/integration/test-sentry-logging.ts (0 hunks)
  • package.json (1 hunks)
💤 Files with no reviewable changes (3)
  • flow-service/tests/integration/test-sentry-init.ts
  • flow-service/tests/integration/test-sentry-logging.ts
  • flow-service/tests/integration/test-log-retention-config.ts
🧰 Additional context used
📓 Path-based instructions (1)
.ai-guidance.md

📄 CodeRabbit Inference Engine (.clinerules/cline-guidance.md)

On every new task, first read the file .ai-guidance.md at the workspace root.

Files:

  • .ai-guidance.md
🧠 Learnings (5)
📚 Learning: applies to sflo-dendron-notes/sflo.contributors.general-guidance.md : read the file `sflo-dendron-no...
Learnt from: CR
PR: semantic-flow/sflow-platform#0
File: .clinerules/cline-guidance.md:0-0
Timestamp: 2025-07-27T01:17:36.738Z
Learning: Applies to sflo-dendron-notes/sflo.contributors.general-guidance.md : Read the file `sflo-dendron-notes/sflo.contributors.general-guidance.md` as referenced by `.ai-guidance.md`.

Applied to files:

  • .ai-guidance.md
📚 Learning: ensure the content of `.ai-guidance.md`, the referenced guidance files, and all ontology files is lo...
Learnt from: CR
PR: semantic-flow/sflow-platform#0
File: .clinerules/cline-guidance.md:0-0
Timestamp: 2025-07-27T01:17:36.738Z
Learning: Ensure the content of `.ai-guidance.md`, the referenced guidance files, and all ontology files is loaded into your context before you begin work.

Applied to files:

  • .ai-guidance.md
📚 Learning: applies to .ai-guidance.md : on every new task, first read the file `.ai-guidance.md` at the workspa...
Learnt from: CR
PR: semantic-flow/sflow-platform#0
File: .clinerules/cline-guidance.md:0-0
Timestamp: 2025-07-27T01:17:36.738Z
Learning: Applies to .ai-guidance.md : On every new task, first read the file `.ai-guidance.md` at the workspace root.

Applied to files:

  • .ai-guidance.md
📚 Learning: applies to sflo-dendron-notes/sflo.contributors.djradon.ai-guidance.md : read the file `sflo-dendron...
Learnt from: CR
PR: semantic-flow/sflow-platform#0
File: .clinerules/cline-guidance.md:0-0
Timestamp: 2025-07-27T01:17:36.738Z
Learning: Applies to sflo-dendron-notes/sflo.contributors.djradon.ai-guidance.md : Read the file `sflo-dendron-notes/sflo.contributors.djradon.ai-guidance.md` as referenced by `.ai-guidance.md`.

Applied to files:

  • .ai-guidance.md
📚 Learning: applies to ontology/** : read all ontology files under the `ontology/` folder as referenced by `.ai-...
Learnt from: CR
PR: semantic-flow/sflow-platform#0
File: .clinerules/cline-guidance.md:0-0
Timestamp: 2025-07-27T01:17:36.738Z
Learning: Applies to ontology/** : Read all ontology files under the `ontology/` folder as referenced by `.ai-guidance.md`.

Applied to files:

  • .ai-guidance.md
🧬 Code Graph Analysis (14)
flow-service/src/config/node-config.default.jsonld (1)
flow-service/src/config/types.ts (1)
  • JSONLDContext (9-15)
flow-core/src/utils/quadstore/quadstore-factory.ts (2)
flow-core/src/types.ts (1)
  • QuadstoreBundle (8-13)
flow-core/src/deps.ts (4)
  • MemoryLevel (18-18)
  • DataFactory (17-17)
  • Quadstore (16-16)
  • Engine (23-23)
flow-service/src/utils/logger.ts (1)
flow-service/src/config/types.ts (3)
  • getConsoleLogLevel (217-220)
  • LogChannelConfig (24-36)
  • LoggingConfig (38-43)
flow-service/src/quadstore-default-bundle.ts (2)
flow-core/src/deps.ts (4)
  • MemoryLevel (18-18)
  • DataFactory (17-17)
  • Quadstore (16-16)
  • Engine (23-23)
flow-core/src/types.ts (1)
  • QuadstoreBundle (8-13)
flow-service/src/config/loaders/env-loader.ts (1)
flow-service/src/config/types.ts (6)
  • NodeConfigInput (119-130)
  • NodeConfig (61-72)
  • NodeConfigContext (138-141)
  • LogChannelConfig (24-36)
  • ServiceConfig (75-85)
  • LoggingConfig (38-43)
flow-service/tests/integration/logging/formatting-direct.test.ts (1)
flow-service/src/utils/logger.ts (2)
  • LogContext (21-67)
  • formatConsoleMessage (221-259)
flow-core/src/platform-constants.ts (2)
flow-service/src/config/index.ts (1)
  • LogLevel (27-27)
flow-service/src/config/types.ts (3)
  • LogChannelConfig (24-36)
  • LoggingConfig (38-43)
  • getConsoleLogLevel (217-220)
flow-core/src/types.ts (1)
flow-core/src/deps.ts (3)
  • Quadstore (16-16)
  • DataFactory (17-17)
  • Engine (23-23)
flow-service/flow-service-config.jsonld (1)
flow-service/src/config/types.ts (6)
  • ServiceConfig (75-85)
  • JSONLDContext (9-15)
  • JSONLDBase (17-21)
  • ServiceConfigInput (107-117)
  • NodeConfig (61-72)
  • ContainedServicesConfig (46-53)
flow-service/tests/integration/quadstore-utils.test.ts (2)
flow-core/src/deps.ts (4)
  • MemoryLevel (18-18)
  • DataFactory (17-17)
  • Quadstore (16-16)
  • assertEquals (3-3)
flow-core/src/utils/quadstore-utils.ts (3)
  • clearGraph (35-50)
  • copyGraph (54-70)
  • countQuadsInStream (8-15)
flow-core/src/utils/rdfjs-utils.ts (1)
flow-core/src/deps.ts (3)
  • DataFactory (17-17)
  • NodeObject (31-31)
  • jsonld (21-21)
flow-service/src/config/resolution/service-config-resolver.ts (4)
flow-service/src/config/config-types.ts (2)
  • ServiceOptions (139-146)
  • ServiceConfigInput (108-118)
flow-service/src/config/loaders/jsonld-loader.ts (1)
  • loadServiceConfig (22-74)
flow-service/src/utils/merge-configs.ts (1)
  • mergeConfigs (16-39)
flow-service/src/config/types.ts (3)
  • ServiceConfigContext (133-136)
  • ServiceConfigInput (107-117)
  • ServiceConfig (75-85)
flow-core/src/utils/quadstore-utils.ts (3)
flow-service/src/quadstore-default-bundle.ts (1)
  • defaultQuadstoreBundle (11-11)
flow-core/src/utils/rdfjs-utils.ts (1)
  • jsonldToQuads (9-25)
flow-core/src/types.ts (1)
  • QuadstoreBundle (8-13)
flow-service/src/utils/mesh-utils.ts (1)
flow-service/src/config/types.ts (1)
  • ServiceConfig (75-85)
🔇 Additional comments (45)
flow-service/deno.json (2)

11-14: Verify relative log path & consistency of --env-file flag

  1. --allow-write=../meshes,./logs assumes flow-service/logs exists. Confirm tasks create or vendor-ignore the directory to avoid runtime errors.
  2. In "dev" the flag --env-file is present without a path. Deno treats this as “use .env”, but "start" passes main.ts as the path. Confirm this asymmetry is intentional.

No blocking issues, just double-check behaviour.


21-21: Formatter setting aligns with new ESLint quote style – looks good

deno.json (1)

18-19: Global quote preference update acknowledged
Consistent with flow-service/deno.json and ESLint rules.

flow-core/src/platform-constants.ts (2)

1-3: LGTM! Excellent use of const assertion for type safety.

The combination of as const assertion with typeof validLogLevels[number] creates a proper union type from the array values, ensuring type safety at compile time.


12-19: Well-implemented validation with comprehensive error handling.

The validation function properly checks both type and value constraints, provides clear error messages, and uses appropriate type assertions. The implementation follows TypeScript best practices for runtime validation.

flow-core/src/deps.ts (2)

20-21: Correct handling of JSON-LD default export.

The import and re-export pattern properly handles the default export from the jsonld npm package, making it available as a named export for consistent usage patterns.


16-24: Dependency versions and security verified

All newly added packages are at their latest released versions and have no reported security advisories:

  • quadstore @ 15.3.0
  • rdf-data-factory @ 2.0.2
  • memory-level @ 3.1.0
  • quadstore-comunica @ 6.2.0
  • jsonld @ 8.3.3
  • @types/jsonld @ 1.5.15
  • @rdfjs/types @ 2.0.1

No vulnerabilities were found via the NPM registry or GitHub advisories.

flow-service/src/config/node-config.default.jsonld (1)

9-9: Consistent MeshRootNodeConfig identifier usage verified

  • No remaining references to defaultNodeConfig found.
  • Only occurrence of defaultMeshRootNodeConfig is in
    flow-service/src/config/node-config.default.jsonld at line 9.

No further updates required.

flow-service/tests/integration/logging/pretty-format-simple.test.ts (1)

11-11: Import path is correct

The import in flow-service/tests/integration/logging/pretty-format-simple.test.ts

import { logger } from '../../../src/utils/logger.ts';

correctly resolves to flow-service/src/utils/logger.ts. No further changes are needed.

flow-service/tests/integration/logging/logger.test.ts (1)

7-7: Import path update is consistent with directory structure changes.

This change aligns with the similar update in pretty-format-simple.test.ts. The pattern suggests the test files were reorganized or the logger module was relocated.

flow-service/src/config/loaders/env-loader.ts (2)

227-227: MeshRootNodeConfig type change verified
The @type update to 'conf:MeshRootNodeConfig' matches the interface in config-types.ts and aligns with all usages in defaults.ts, index.ts, and loader modules. No remaining references to 'conf:NodeConfig' were found.


11-13: External validateLogLevel Import and Behavior Verified

The validateLogLevel function in flow-core/src/platform-constants.ts:

  • Has the signature validateLogLevel(level: unknown): LogLevel
  • Throws a descriptive Error when the input is not a valid log level
  • Returns the validated LogLevel otherwise

In env-loader.ts, any thrown Error is caught and wrapped (or re-thrown if already a ConfigError), ensuring invalid log levels still surface as ConfigError—matching the original local implementation’s semantics.

No changes required.

flow-service/src/routes/weave.ts (2)

19-20: Configuration parameter removal aligns with singleton pattern.

The removal of the config parameter from createWeaveRoutes is consistent with the architectural shift to singleton configuration management. Ensure that any configuration access needed within route handlers uses the appropriate singleton accessor.


93-95: Minor formatting improvement.

The logging statement formatting change improves readability without affecting functionality.

flow-core/src/utils/quadstore/quadstore-factory.ts (1)

1-17: Well-structured factory function.

The factory function provides good encapsulation of quadstore bundle creation with proper async handling and clear return types.

flow-core/src/types.ts (1)

8-13: Well-designed interface with good type safety.

The QuadstoreBundle interface provides excellent type safety with appropriate generic constraints and flexibility with the optional engine property. The design supports various backend implementations while maintaining type consistency.

flow-service/tests/integration/quadstore-accessor.test.ts (1)

5-44: Well-structured integration test with comprehensive coverage.

The test effectively validates the complete Quadstore workflow from data insertion to SPARQL querying. The test data structure, query construction, and assertions are all appropriate for verifying the integration functionality.

flow-core/src/utils/rdfjs-utils.ts (1)

9-25: Excellent implementation of JSON-LD to RDF conversion.

The function correctly uses jsonld.toRDF() for conversion and properly handles graph assignment. The logic for distinguishing between default and named graphs is sound, and the quad remapping preserves all RDF components while updating the graph context appropriately.

flow-service/src/utils/mesh-utils.ts (1)

3-3: Good refactoring to use singleton configuration accessor.

The import change from a parameterized config to the singleton accessor aligns well with the architectural refactor described in the PR objectives.

flow-service/src/services/metadata-composer.ts (1)

1-1: Good refactoring to singleton configuration accessor.

The import change aligns with the architectural shift to using a singleton configuration accessor, eliminating the need to pass config as a parameter.

eslint.config.mjs (1)

4-19: Well-configured ESLint setup for TypeScript.

The configuration properly targets TypeScript files, uses the appropriate parser, and enforces consistent string quoting that aligns with the codebase formatting changes. The flat config format is correctly structured.

flow-service/main.ts (2)

15-15: Good error handling for configuration initialization

The error handling properly catches configuration failures and exits the service, preventing it from running with invalid configuration.


5-5: No initialization race detected

The defaultQuadstoreBundle uses a top-level await to open the Quadstore before exporting the engine, and in main.ts we call and await createServiceConfig() (which loads and merges all graphs) before any singletonServiceConfigAccessor.get…() calls. The accessor is fully initialized and the store is opened prior to its first use, so no race condition exists.

flow-service/flow-service-config.jsonld (1)

15-16: Configuration values match validation requirements

The addition of fsvc:host ensures the configuration passes validation, and the port value is within the valid range (1-65535).

flow-service/tests/integration/logging/formatting-direct.test.ts (1)

47-48: Good refactoring to use shared formatting function

Using the exported formatConsoleMessage from the logger module instead of a local implementation ensures the test validates the actual production formatting logic.

Also applies to: 125-125

flow-core/tests/unit/quadstore-utils.test.ts (2)

5-24: Good test structure and isolation

The tests properly isolate each scenario with unique graph URNs and clean up before and after operations. The assertions are clear and test the expected behavior.


64-85: Add cleanup for graphs in copyGraph test

The test should clean up both source and target graphs after the test completes for consistency with other tests.

   assertEquals(countSource, 1);
   assertEquals(countTarget, 1);
+
+  // Cleanup
+  await clearGraph(sourceGraph, testQuadstoreBundle);
+  await clearGraph(targetGraph, testQuadstoreBundle);
 });

Likely an incorrect or invalid review comment.

flow-service/src/config/resolution/service-config-loader.ts (1)

28-33: No changes needed for error handling in loadServiceConfig

The JSDoc on loadServiceConfig (jsonld-loader.ts) clearly specifies that it:

  • Returns null when the file is missing
  • Throws a ConfigError for invalid JSON, wrong @type, or other failures

Since callers of loadServiceConfig don’t catch errors, any parsing or validation failures will bubble up as intended. No additional error‐handling or documentation updates are required here.

flow-service/src/config/resolution/service-config-accessor.ts (1)

70-72: Remove duplicate SPARQL engine check

The engine check is redundant since getMeshPaths doesn't use querySingleValue but should follow the same pattern.

Consider refactoring getMeshPaths to use a similar pattern or extract the engine check to a shared method:

   async getMeshPaths(): Promise<string[]> {
     const sparql = `...`;
-    if (!this.bundle.engine) {
-      throw new Error('SPARQL engine not initialized in Quadstore bundle');
-    }
     const values: string[] = [];
-    const bindingsStream = await this.bundle.engine.queryBindings(sparql, { sources: [this.bundle.store] });
+    try {
+      if (!this.bundle.engine) {
+        throw new Error('SPARQL engine not initialized in Quadstore bundle');
+      }
+      const bindingsStream = await this.bundle.engine.queryBindings(sparql, { sources: [this.bundle.store] });
+    } catch (error) {
+      await handleCaughtError(error, 'Failed to execute SPARQL query for mesh paths');
+      throw new Error('Failed to execute SPARQL query for mesh paths');
+    }

Likely an incorrect or invalid review comment.

flow-service/src/config/loaders/jsonld-loader.ts (7)

8-12: LGTM! Clean import restructuring.

The imports have been properly updated to use the new MeshRootNodeConfigInput type and reorganized config-types imports.


22-74: Well-structured error handling and validation.

The function properly handles all error cases with appropriate error messages and maintains the error chain through the cause parameter.


84-140: Consistent renaming and proper path resolution.

The function has been correctly renamed to match the new MeshRootNodeConfig naming convention and includes proper absolute path resolution to prevent relative path issues.


147-171: LGTM! Standard save implementation.

The function correctly handles directory creation and JSON formatting with proper error handling.


178-204: Consistent renaming with proper implementation.

The function has been correctly renamed and updated to use the new MeshRootNodeConfigInput type while maintaining the same robust implementation pattern.


250-267: Proper handling of optional configuration.

The function correctly defaults to true for inheritance when the property is unspecified or when configuration cannot be loaded, which is a sensible default behavior.


274-282: Improved function naming and type safety.

The function has been renamed to follow camelCase convention and the parameter type has been appropriately narrowed to NodeObject, eliminating the need for the initial object check.

flow-service/src/config/loaders/quadstore-loader.ts (1)

1-5: Good modular design with clear separation of concerns.

The imports are well-organized, separating quadstore utilities from configuration types and constants.

flow-core/src/utils/quadstore-utils.ts (1)

8-15: Well-implemented stream counting utility.

The function correctly handles RDF streams with proper event handling for data, end, and error events.

flow-service/src/config/resolution/service-config-resolver.ts (2)

13-22: Clean import organization for the new graph-based approach.

The imports clearly separate concerns between platform constants, loaders, and quadstore operations.


24-71: Well-structured graph-based configuration resolution.

The refactored function follows a clear flow: load platform defaults → load and merge input configs → load to Quadstore → merge graphs. The error handling is comprehensive and maintains proper error context.

flow-service/src/config/config-types.ts (1)

8-9: Good use of shared JSON-LD types.

Importing NodeObject and ContextDefinition from core deps promotes type consistency across the codebase.

flow-service/src/config/defaults.ts (2)

8-206: Well-structured configuration refactoring

The configuration defaults have been successfully refactored to support the new graph-based approach:

  • Consistent use of JSON-LD structure with explicit @id fields
  • Proper typing with the new MeshRootNodeConfig type
  • Clean separation of platform vs service defaults
  • Environment-specific overrides are well-organized

The changes align well with the PR's objective of implementing a singleton pattern for configuration data management.


37-37: Verify the updated template paths

I couldn’t locate default-resource-page.html under /_assets/_templates/. Please confirm that this path aligns with your project’s static‐assets directory. If the actual folder structure differs, update the template references in flow-service/src/config/defaults.ts accordingly.

Points to check:

  • No file found at /_assets/_templates/default-resource-page.html
  • Does the file live under a different path? (e.g., /assets/_templates/, /assets/templates/, etc.)
  • Update lines 37 (and 68) in flow-service/src/config/defaults.ts to match the real directory layout.
flow-service/src/config/index.ts (2)

89-99: Clean separation of concerns in createServiceConfig

The simplified createServiceConfig function now properly follows the single responsibility principle by only orchestrating resolution and validation, without returning an accessor. This aligns well with the singleton pattern where the accessor is accessed separately via singletonServiceConfigAccessor.


1-100: Excellent modularization of configuration system

The refactoring successfully modularizes the configuration system:

  • Clear separation between resolution, validation, and access concerns
  • Proper use of singleton pattern for configuration access
  • Well-organized exports that expose only necessary interfaces
  • Clean transition from in-memory merging to graph-based configuration

The changes create a more maintainable and scalable configuration management system.

Comment on lines +35 to +50
export async function clearGraph(
graph: RDF.NamedNode,
{
store
}: { store: Quadstore } = defaultQuadstoreBundle
): Promise<number> {
const matchStream = store.match(undefined, undefined, undefined, graph);
const count = await countQuadsInStream(matchStream);

if (count > 0) {
const delStream = store.match(undefined, undefined, undefined, graph);
await store.delStream(delStream as any);
}

return count;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize graph clearing and fix type assertion.

The function performs two passes over the data when one would suffice. Also, the as any type assertion should be avoided.

 export async function clearGraph(
   graph: RDF.NamedNode,
   {
     store
   }: { store: Quadstore } = defaultQuadstoreBundle
 ): Promise<number> {
-  const matchStream = store.match(undefined, undefined, undefined, graph);
-  const count = await countQuadsInStream(matchStream);
-
-  if (count > 0) {
-    const delStream = store.match(undefined, undefined, undefined, graph);
-    await store.delStream(delStream as any);
-  }
-
-  return count;
+  const quads = [];
+  const stream = store.match(undefined, undefined, undefined, graph);
+  
+  for await (const quad of stream) {
+    quads.push(quad);
+  }
+  
+  if (quads.length > 0) {
+    await store.multiDel(quads);
+  }
+  
+  return quads.length;
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In flow-core/src/utils/quadstore-utils.ts lines 35 to 50, the clearGraph
function currently matches the graph twice and uses an unsafe 'as any' type
assertion on delStream. Refactor the function to perform a single match stream
and delete operation without counting first, and replace the 'as any' assertion
with the correct type expected by store.delStream to ensure type safety.

Comment on lines +54 to +70
export async function copyGraph(
sourceGraph: RDF.NamedNode,
targetGraph: RDF.NamedNode,
{
store,
df,
}: { store: Quadstore, df: DataFactory } = defaultQuadstoreBundle
): Promise<number> {
const stream = store.match(undefined, undefined, undefined, sourceGraph);
const quads = [];
for await (const q of stream as any) {
const newQuad = df.quad(q.subject, q.predicate, q.object, targetGraph);
quads.push(newQuad);
}
await store.multiPut(quads);
return quads.length;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix type assertion and consider memory usage for large graphs.

The function loads all quads into memory before copying, which could cause issues with large graphs. Also, avoid the as any type assertion.

 export async function copyGraph(
   sourceGraph: RDF.NamedNode,
   targetGraph: RDF.NamedNode,
   {
     store,
     df,
   }: { store: Quadstore, df: DataFactory } = defaultQuadstoreBundle
 ): Promise<number> {
   const stream = store.match(undefined, undefined, undefined, sourceGraph);
   const quads = [];
-  for await (const q of stream as any) {
+  for await (const q of stream) {
     const newQuad = df.quad(q.subject, q.predicate, q.object, targetGraph);
     quads.push(newQuad);
   }
   await store.multiPut(quads);
   return quads.length;
 }

For very large graphs, consider implementing a streaming copy that processes quads in batches to avoid memory issues.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function copyGraph(
sourceGraph: RDF.NamedNode,
targetGraph: RDF.NamedNode,
{
store,
df,
}: { store: Quadstore, df: DataFactory } = defaultQuadstoreBundle
): Promise<number> {
const stream = store.match(undefined, undefined, undefined, sourceGraph);
const quads = [];
for await (const q of stream as any) {
const newQuad = df.quad(q.subject, q.predicate, q.object, targetGraph);
quads.push(newQuad);
}
await store.multiPut(quads);
return quads.length;
}
export async function copyGraph(
sourceGraph: RDF.NamedNode,
targetGraph: RDF.NamedNode,
{
store,
df,
}: { store: Quadstore, df: DataFactory } = defaultQuadstoreBundle
): Promise<number> {
const stream = store.match(undefined, undefined, undefined, sourceGraph);
const quads = [];
for await (const q of stream) {
const newQuad = df.quad(q.subject, q.predicate, q.object, targetGraph);
quads.push(newQuad);
}
await store.multiPut(quads);
return quads.length;
}
🤖 Prompt for AI Agents
In flow-core/src/utils/quadstore-utils.ts around lines 54 to 70, the function
currently collects all quads into an array before writing, which can cause high
memory usage for large graphs, and it uses an unsafe 'as any' type assertion. To
fix this, remove the 'as any' assertion by properly typing the stream, and
refactor the function to process quads in batches by accumulating a limited
number of quads before calling store.multiPut, repeating until all quads are
processed, to reduce memory consumption.

Comment on lines +110 to +129
export async function createNewGraphFromJsonLd(
inputJsonLd: NodeObject,
options: CreateGraphOptions = {}
): Promise<number> {
const {
overwrite = false,
graphName = null,
bundle = defaultQuadstoreBundle,
} = options;

const { store, df } = bundle;
const graph = graphName ? df.namedNode(graphName) : df.defaultGraph();
const quads = await jsonldToQuads(inputJsonLd, graph);
if (overwrite && graphName) clearGraph(df.namedNode(graphName));

// Put quads into the store
await store.multiPut(quads);

return quads.length;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Critical: Missing await for async clearGraph call.

The clearGraph function is asynchronous but is not awaited on line 123, which could lead to race conditions where quads are inserted before the graph is cleared.

   const { store, df } = bundle;
   const graph = graphName ? df.namedNode(graphName) : df.defaultGraph();
   const quads = await jsonldToQuads(inputJsonLd, graph);
-  if (overwrite && graphName) clearGraph(df.namedNode(graphName));
+  if (overwrite && graphName) await clearGraph(df.namedNode(graphName), bundle);

   // Put quads into the store
   await store.multiPut(quads);

   return quads.length;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function createNewGraphFromJsonLd(
inputJsonLd: NodeObject,
options: CreateGraphOptions = {}
): Promise<number> {
const {
overwrite = false,
graphName = null,
bundle = defaultQuadstoreBundle,
} = options;
const { store, df } = bundle;
const graph = graphName ? df.namedNode(graphName) : df.defaultGraph();
const quads = await jsonldToQuads(inputJsonLd, graph);
if (overwrite && graphName) clearGraph(df.namedNode(graphName));
// Put quads into the store
await store.multiPut(quads);
return quads.length;
}
export async function createNewGraphFromJsonLd(
inputJsonLd: NodeObject,
options: CreateGraphOptions = {}
): Promise<number> {
const {
overwrite = false,
graphName = null,
bundle = defaultQuadstoreBundle,
} = options;
const { store, df } = bundle;
const graph = graphName ? df.namedNode(graphName) : df.defaultGraph();
const quads = await jsonldToQuads(inputJsonLd, graph);
if (overwrite && graphName) await clearGraph(df.namedNode(graphName), bundle);
// Put quads into the store
await store.multiPut(quads);
return quads.length;
}
🤖 Prompt for AI Agents
In flow-core/src/utils/quadstore-utils.ts lines 110 to 129, the call to the
asynchronous function clearGraph on line 123 is missing an await, which can
cause race conditions by inserting quads before the graph is cleared. To fix
this, add the await keyword before clearGraph to ensure the graph is fully
cleared before proceeding with inserting new quads.

Comment on lines +32 to 40
const meshPaths = await config.getMeshPaths();
if (meshPaths.length > 0) {
for (const meshPath of meshPaths) {
const absolutePath = resolve(Deno.cwd(), meshPath);
console.log(` Configured mesh path: ${absolutePath}`);
}
} else {
console.log(` Mesh Paths: none configured`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for async config operations

The async config accessor calls could fail but there's no error handling.

Wrap the config calls in try-catch blocks:

 export async function logStartupConfiguration(): Promise<void> {
   const now = new Date();
   // ... timestamp code ...
   
   console.log(
     `🔧 Flow Service initializing at ${timestamp} with configuration:`,
   );
 
-  const meshPaths = await config.getMeshPaths();
+  try {
+    const meshPaths = await config.getMeshPaths();
+  } catch (error) {
+    console.error('Failed to retrieve mesh paths:', error);
+    const meshPaths = [];
+  }

Apply similar error handling to logStartupUrls().

Also applies to: 63-65

🤖 Prompt for AI Agents
In flow-service/src/utils/startup-logger.ts around lines 32 to 40 and also lines
63 to 65, the async calls to config.getMeshPaths() and other config accessors
lack error handling. Wrap these async calls in try-catch blocks to catch and log
any errors that occur during the config retrieval. Apply the same try-catch
error handling pattern to the logStartupUrls() function to ensure all async
config operations are safely handled.


console.log(`📍 Root: ${baseUrl}/`);
console.log(`📚 API documentation: ${baseUrl}${MESH.API_PORTAL_ROUTE}`);
console.log(` API documentation: ${baseUrl}${MESH.API_PORTAL_ROUTE}`);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix broken Unicode character

The Unicode character appears corrupted in the log output.

-  console.log(`� API documentation: ${baseUrl}${MESH.API_PORTAL_ROUTE}`);
+  console.log(`📖 API documentation: ${baseUrl}${MESH.API_PORTAL_ROUTE}`);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log(` API documentation: ${baseUrl}${MESH.API_PORTAL_ROUTE}`);
console.log(`📖 API documentation: ${baseUrl}${MESH.API_PORTAL_ROUTE}`);
🤖 Prompt for AI Agents
In flow-service/src/utils/startup-logger.ts at line 68, the Unicode character in
the console.log statement is corrupted and not displaying correctly. Replace the
broken Unicode character with a valid and intended Unicode symbol or remove it
entirely to ensure proper display in the log output.

Comment on lines +6 to +10
Deno.test('Quadstore clearGraph and copyGraph utilities', async () => {
const backend = new MemoryLevel();
const df = new DataFactory();
const store = new Quadstore({ backend, dataFactory: df });
await store.open();
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add proper cleanup by closing the store after test completion

The test opens the quadstore but never closes it, which could lead to resource leaks in the test suite.

Add cleanup at the end of the test:

   // Verify graphB still has 1 quad
   count = await countQuadsInGraph(graphB, store);
   assertEquals(count, 1);
+
+  await store.close();
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Deno.test('Quadstore clearGraph and copyGraph utilities', async () => {
const backend = new MemoryLevel();
const df = new DataFactory();
const store = new Quadstore({ backend, dataFactory: df });
await store.open();
Deno.test('Quadstore clearGraph and copyGraph utilities', async () => {
const backend = new MemoryLevel();
const df = new DataFactory();
const store = new Quadstore({ backend, dataFactory: df });
await store.open();
// … the rest of your test setup and assertions …
// Verify graphB still has 1 quad
let count = await countQuadsInGraph(graphB, store);
assertEquals(count, 1);
await store.close();
});
🤖 Prompt for AI Agents
In flow-service/tests/integration/quadstore-utils.test.ts around lines 6 to 10,
the test opens the quadstore but does not close it, risking resource leaks. Add
a call to store.close() at the end of the test to properly clean up resources
after test completion.

djradon added 2 commits August 2, 2025 16:06
- Updated the import of Quadstore in deps.ts to use the beta version.
- Modified clearGraph function to remove return count and log the number of quads after deletion.
- Enhanced error handling in createQuadstoreBundle to catch and log errors when opening the quadstore.
- Updated tests for clearGraph to reflect changes in return type and added assertions for graph state before and after clearing.
- Cleaned up type assertions in various files to improve type safety.
- Removed unnecessary console logs and comments in service configuration loaders and validators.
- Updated metadata-composer.ts to use double quotes for consistency and modified the attributedTo field to use a hardcoded URL.
- Refactored error handling in errors.ts to improve structured logging and context management.
- Removed the logger.ts file and replaced it with a new service-logger.ts that provides service-specific logging configuration and context.
- Updated mesh-utils.ts to use the new service logger and improved logging context for mesh registration.
- Adjusted startup-logger.ts to ensure type safety for enabled services.
- Modified various test files to import from the new service-logger.ts and updated logging calls to align with the new structured logging format.
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: 9

♻️ Duplicate comments (1)
flow-service/main.ts (1)

110-111: Route creation functions still need singleton accessor integration.

As noted in the previous review, createMeshesRoutes() and createWeaveRoutes() no longer receive a config parameter but haven't been updated to use singletonServiceConfigAccessor() internally. The implementations in flow-service/src/routes/meshes.ts and flow-service/src/routes/weave.ts need to import and call the singleton accessor for any configuration they require.

🧹 Nitpick comments (9)
flow-core/tests/integration/logger/formatters.test.ts (1)

1-147: Consider using a test framework for automated verification.

While these integration tests effectively demonstrate the formatting functions, they rely on manual verification of console output. Consider using Deno's built-in test framework with assertions for automated testing:

Example refactor for one test:

import { assertEquals } from "https://deno.land/std/testing/asserts.ts";

Deno.test("formatConsoleMessage should format messages correctly", () => {
  const context: LogContext = {
    operation: 'startup',
    component: 'config-resolver',
    serviceContext: {
      serviceName: 'flow-core-test',
      serviceVersion: '1.0.0'
    }
  };
  
  const result = formatConsoleMessage('INFO', 'Test message', context);
  // Assert the result contains expected parts
  assert(result.includes('INFO'));
  assert(result.includes('Test message'));
  assert(result.includes('startup'));
});
flow-core/src/utils/logger/structured-logger.ts (1)

194-215: Consider optimizing file rotation checks.

The rotateIfNeeded() is called on every write operation, which could impact performance for high-frequency logging. Consider implementing a time-based or write-count-based check to reduce filesystem operations.

 private async writeToFile(
   level: LogLevel,
   message: string,
   context?: LogContext,
 ): Promise<void> {
   try {
     const fileLogger = await getGlobalFileLogger();
     if (fileLogger) {
-      await fileLogger.rotateIfNeeded();
+      // Only check rotation periodically or based on write count
+      // This could be managed by the FileLogger internally
 
       const fileFormatted = formatStructuredMessage(
         level,
         message,
         context,
         this.config.serviceContext,
       );
       await fileLogger.writeToFile(fileFormatted);
     }
   } catch (err) {
     console.error(`Failed to write to file log: ${err}`);
   }
 }
flow-core/src/utils/logger/file-logger.ts (1)

43-56: Consider making queue overflow handling configurable.

When the queue is full, the logger drops the oldest half of entries and logs to console. Consider making this behavior configurable (e.g., drop oldest, drop newest, or block) and potentially emit an event for monitoring.

 async writeToFile(content: string): Promise<void> {
   if (this.writeQueue.length >= this.maxQueueSize) {
     console.error(
       `Log queue full (${this.maxQueueSize} items), dropping oldest entries`,
     );
+    // Consider emitting an event or metric for monitoring
+    // this.emit('queueOverflow', { queueSize: this.writeQueue.length });
     this.writeQueue = this.writeQueue.slice(
       -Math.floor(this.maxQueueSize / 2),
     );
   }
   this.writeQueue.push(content);
   if (!this.isWriting) {
     await this.processWriteQueue();
   }
 }
flow-service/src/config/resolution/service-config-resolver.ts (1)

54-56: Track the TODO for mesh node configuration loading.

The TODO comment indicates missing functionality for loading mesh node configuration. This should be tracked properly to ensure it's not forgotten.

Would you like me to create an issue to track the implementation of loadInputMeshRootNodeConfig?

flow-core/src/utils/logger/error-handlers.ts (1)

88-400: Consider refactoring for improved maintainability.

While the comprehensive error handling is excellent, the function is quite long (300+ lines). Consider extracting error-type-specific handlers into separate functions to improve readability and maintainability.

// Example refactor approach:
private async logFlowServiceError(
  error: Error & { code?: string; context?: unknown },
  formatErrorMsg: (type: string, msg: string) => string,
  baseContext: LogContext
): Promise<void> {
  // Extract FlowServiceError handling logic
}

private async logValidationError(
  error: Error & { code?: string; field?: string; context?: unknown },
  formatErrorMsg: (type: string, msg: string) => string,
  baseContext: LogContext
): Promise<void> {
  // Extract ValidationError handling logic
}

// Then in handleCaughtError:
if (e.name === 'FlowServiceError') {
  await this.logFlowServiceError(e, formatErrorMsg, baseContext);
} else if (e.name === 'ValidationError') {
  await this.logValidationError(e, formatErrorMsg, baseContext);
}
// etc.
flow-service/src/config/config-types.ts (1)

60-61: Complete the TODO comment

The TODO comment on line 60 appears to be incomplete. Please provide the intended new name for the interface to maintain code clarity.

-// TODO rename to 
+// TODO rename to <intended_name>
flow-core/src/utils/logger/sentry-logger.ts (1)

14-15: Module-level mutable state may cause issues

The sentryInitialized variable is module-level mutable state that could cause issues in concurrent or testing scenarios. The resetSentry function allows external modification of this state, which could lead to unexpected behavior.

Consider encapsulating the initialization state in a class or using a more robust singleton pattern to manage Sentry's lifecycle, especially since this is meant to be used across the application.

Also applies to: 276-278

flow-core/src/utils/logger/formatters.ts (1)

201-255: Consider edge cases in context merging

The mergeLogContext function performs shallow merging for nested objects. This approach might lose deeply nested properties if they exist at multiple levels.

Consider using a more robust deep merge utility or documenting the shallow merge behavior to set clear expectations:

+/**
+ * Merge multiple LogContext objects with proper precedence
+ * @param contexts - Array of LogContext objects to merge (later entries take precedence)
+ * @returns Merged LogContext
+ * @note Performs shallow merge on nested objects (performanceMetrics, configContext, etc.)
+ */
 export function mergeLogContext(...contexts: (LogContext | undefined)[]): LogContext {
flow-service/src/config/index.ts (1)

11-18: Consider making graph URIs configurable

The graph URIs are hardcoded to use http://localhost/graph/. This might not be suitable for all deployment environments or when multiple instances are running.

Consider making these URIs configurable through environment variables or configuration:

+const GRAPH_BASE_URI = Deno.env.get('FLOW_GRAPH_BASE_URI') || 'http://localhost/graph/';
+
 export const CONFIG_GRAPH_NAMES = {
-  platformServiceDefaults: 'http://localhost/graph/platformServiceDefaults',
-  platformImplicitMeshRootNodeConfig: 'http://localhost/graph/platformImplicitMeshRootNodeConfig',
-  inputServiceConfig: 'http://localhost/graph/inputServiceConfig',
-  inputMeshRootNodeConfig: 'http://localhost/graph/inputMeshRootNodeConfig',
-  mergedServiceConfig: 'http://localhost/graph/mergedServiceConfig',
+  platformServiceDefaults: `${GRAPH_BASE_URI}platformServiceDefaults`,
+  platformImplicitMeshRootNodeConfig: `${GRAPH_BASE_URI}platformImplicitMeshRootNodeConfig`,
+  inputServiceConfig: `${GRAPH_BASE_URI}inputServiceConfig`,
+  inputMeshRootNodeConfig: `${GRAPH_BASE_URI}inputMeshRootNodeConfig`,
+  mergedServiceConfig: `${GRAPH_BASE_URI}mergedServiceConfig`,
   // Per-node effective configs could be stored with dynamic graph names
 };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2633986 and 9d7a11e.

⛔ Files ignored due to path filters (3)
  • deno.lock is excluded by !**/*.lock
  • flow-service/deno.lock is excluded by !**/*.lock
  • flow-service/logs/test-pretty-direct.log is excluded by !**/*.log
📒 Files selected for processing (38)
  • .ai-guidance.md (1 hunks)
  • flow-core/docs/error-handling-usage.md (1 hunks)
  • flow-core/src/deps.ts (1 hunks)
  • flow-core/src/utils/logger/error-handlers.ts (1 hunks)
  • flow-core/src/utils/logger/file-logger.ts (1 hunks)
  • flow-core/src/utils/logger/formatters.ts (1 hunks)
  • flow-core/src/utils/logger/index.ts (1 hunks)
  • flow-core/src/utils/logger/sentry-logger.ts (1 hunks)
  • flow-core/src/utils/logger/structured-logger.ts (1 hunks)
  • flow-core/src/utils/logger/types.ts (1 hunks)
  • flow-core/src/utils/quadstore-utils.ts (1 hunks)
  • flow-core/src/utils/quadstore/quadstore-factory.ts (1 hunks)
  • flow-core/tests/integration/logger/error-handlers.test.ts (1 hunks)
  • flow-core/tests/integration/logger/formatters.test.ts (1 hunks)
  • flow-core/tests/integration/logger/logger.test.ts (1 hunks)
  • flow-service/deno.json (1 hunks)
  • flow-service/main.ts (5 hunks)
  • flow-service/src/config/config-types.ts (6 hunks)
  • flow-service/src/config/index.ts (2 hunks)
  • flow-service/src/config/loaders/jsonld-loader.ts (7 hunks)
  • flow-service/src/config/node-config.default.jsonld (2 hunks)
  • flow-service/src/config/resolution/service-config-accessor.ts (1 hunks)
  • flow-service/src/config/resolution/service-config-resolver.ts (1 hunks)
  • flow-service/src/routes/health.ts (3 hunks)
  • flow-service/src/routes/meshes.ts (5 hunks)
  • flow-service/src/routes/weave.ts (3 hunks)
  • flow-service/src/services/metadata-composer.ts (2 hunks)
  • flow-service/src/utils/errors.ts (2 hunks)
  • flow-service/src/utils/logger.ts (0 hunks)
  • flow-service/src/utils/mesh-utils.ts (2 hunks)
  • flow-service/src/utils/service-logger.ts (1 hunks)
  • flow-service/src/utils/startup-logger.ts (3 hunks)
  • flow-service/tests/integration/logging/formatting-direct.test.ts (3 hunks)
  • flow-service/tests/integration/logging/handle-caught-error.test.ts (1 hunks)
  • flow-service/tests/integration/logging/logger.test.ts (1 hunks)
  • flow-service/tests/integration/logging/pretty-format-simple.test.ts (2 hunks)
  • flow-service/tests/integration/logging/sentry-init.test.ts (1 hunks)
  • flow-service/tests/integration/logging/sentry-logging.test.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • flow-service/src/utils/logger.ts
✅ Files skipped from review due to trivial changes (2)
  • flow-service/src/config/node-config.default.jsonld
  • flow-service/tests/integration/logging/handle-caught-error.test.ts
🚧 Files skipped from review as they are similar to previous changes (16)
  • flow-service/tests/integration/logging/sentry-init.test.ts
  • .ai-guidance.md
  • flow-service/deno.json
  • flow-service/tests/integration/logging/sentry-logging.test.ts
  • flow-service/tests/integration/logging/pretty-format-simple.test.ts
  • flow-service/src/utils/errors.ts
  • flow-service/src/routes/weave.ts
  • flow-service/tests/integration/logging/logger.test.ts
  • flow-core/src/utils/quadstore/quadstore-factory.ts
  • flow-service/src/utils/startup-logger.ts
  • flow-service/tests/integration/logging/formatting-direct.test.ts
  • flow-service/src/services/metadata-composer.ts
  • flow-service/src/config/resolution/service-config-accessor.ts
  • flow-service/src/routes/meshes.ts
  • flow-service/src/config/loaders/jsonld-loader.ts
  • flow-core/src/utils/quadstore-utils.ts
🧰 Additional context used
🧬 Code Graph Analysis (5)
flow-service/src/routes/health.ts (1)
flow-service/src/utils/service-logger.ts (1)
  • logger (57-57)
flow-core/tests/integration/logger/formatters.test.ts (3)
flow-core/src/utils/logger/index.ts (5)
  • LogContext (8-8)
  • formatConsoleMessage (24-24)
  • formatStructuredMessage (23-23)
  • createContextSummary (26-26)
  • mergeLogContext (27-27)
flow-core/src/utils/logger/types.ts (1)
  • LogContext (11-78)
flow-core/src/utils/logger/formatters.ts (4)
  • formatConsoleMessage (112-152)
  • formatStructuredMessage (79-103)
  • createContextSummary (182-194)
  • mergeLogContext (201-255)
flow-core/src/utils/logger/types.ts (4)
flow-core/src/utils/logger/index.ts (7)
  • LogContext (8-8)
  • StructuredLogger (9-9)
  • LogLevel (15-15)
  • LogLevel (18-18)
  • LoggerConfig (10-10)
  • ErrorSeverity (11-11)
  • ErrorHandlingOptions (12-12)
flow-service/src/config/index.ts (1)
  • LogLevel (27-27)
flow-service/src/config/config-types.ts (1)
  • LogLevel (186-186)
flow-service/src/config/types.ts (1)
  • LogChannelConfig (24-36)
flow-core/src/utils/logger/index.ts (2)
flow-core/src/utils/logger/types.ts (1)
  • StructuredLogger (84-146)
flow-core/src/utils/logger/structured-logger.ts (3)
  • createLogger (331-336)
  • EnhancedStructuredLogger (277-323)
  • createEnhancedLogger (344-349)
flow-service/src/utils/service-logger.ts (3)
flow-core/src/utils/logger/index.ts (5)
  • LoggerConfig (10-10)
  • EnhancedStructuredLogger (33-33)
  • createEnhancedLogger (35-35)
  • StructuredLogger (9-9)
  • LogContext (8-8)
flow-core/src/utils/logger/types.ts (3)
  • LoggerConfig (163-199)
  • StructuredLogger (84-146)
  • LogContext (11-78)
flow-service/src/config/loaders/env-loader.ts (1)
  • loadEnvConfig (18-209)
🔇 Additional comments (27)
flow-service/src/routes/health.ts (1)

2-2: LGTM! Structured logging improvements enhance observability.

The migration from the legacy logger to the new structured logger with rich contextual metadata is well-implemented. The new format provides better observability with operation categorization and proper nesting of API context information.

Also applies to: 38-46, 58-61

flow-core/tests/integration/logger/logger.test.ts (1)

1-94: Excellent comprehensive integration test for the logging system.

This test effectively validates the enhanced structured logger functionality with:

  • Multiple log levels with rich contextual metadata
  • Performance metrics, API context, error context, and configuration context
  • Contextual logger feature (withContext) validation
  • Clear user guidance for verification

The test coverage is thorough and follows good practices for integration testing.

flow-service/main.ts (1)

16-31: LGTM! Configuration refactoring and error handling improvements are well-implemented.

The migration to the singleton service config accessor pattern with proper async handling and the enhanced structured error handling with rich LogContext metadata significantly improve the codebase maintainability and observability.

Also applies to: 65-68, 134-149

flow-core/tests/integration/logger/error-handlers.test.ts (1)

1-187: Excellent comprehensive error handling integration test.

This test provides thorough validation of the enhanced error handling system with:

  • Multiple error types (Error objects and strings)
  • Rich LogContext configurations covering all context types
  • Context merging functionality testing
  • Comprehensive coverage of all optional LogContext fields

The test scenarios effectively validate the integration between error handling and structured logging.

flow-core/src/deps.ts (1)

16-40: LGTM! Excellent dependency centralization for the new architecture.

The expansion of exports effectively centralizes key dependencies for:

  • RDF and quadstore components (Quadstore, DataFactory, MemoryLevel, Engine)
  • JSON-LD types and utilities with proper ESM compatibility
  • RDF types namespace for consistent type usage
  • Sentry integration for error reporting

This centralization improves dependency management and supports the new quadstore-based configuration system mentioned in the AI summary.

flow-service/src/utils/mesh-utils.ts (1)

1-66: Well-implemented refactoring to async configuration access and structured logging.

The changes properly address the previous review comment about async handling. The function is correctly marked as async and uses await when calling config.getMeshPaths(). The enhanced structured logging with operation, component, and metadata fields provides excellent observability for mesh registry initialization.

flow-core/docs/error-handling-usage.md (1)

18-18: Verify import path configuration in project

I couldn’t locate any TypeScript path aliases, Deno import maps, webpack aliases, Babel module-resolver settings, or package exports for @flow/core or @flow/service. Please confirm that your build/runtime configuration supports these module prefixes—otherwise update the docs or the project’s path mappings.

Files & locations to check in docs:

  • flow-core/docs/error-handling-usage.md: lines 18, 35
  • flow-core/docs/error-handling-usage.md: line 239
flow-core/src/utils/logger/structured-logger.ts (5)

24-42: LGTM! Well-structured logger initialization.

The constructor properly handles configuration merging with sensible defaults. Good design choice to enable all channels by default for visibility during development.


107-136: Excellent context scoping implementation.

The context creation methods maintain immutability by returning new logger instances. Good use of crypto.randomUUID() for operation tracking and performance metrics initialization.


241-272: Good defensive programming practices.

Excellent use of object spread operators to prevent external mutation of internal state. The ability to update configuration at runtime is useful for dynamic log level adjustments.


274-323: Well-implemented enhanced logger with Error object support.

The overloaded method signatures provide flexibility while maintaining backward compatibility. Good use of instanceof for parameter discrimination.


325-349: Clean factory function implementation.

Good separation between standard and enhanced logger creation, giving users flexibility to choose based on their error handling needs.

flow-core/src/utils/logger/file-logger.ts (4)

11-26: Well-designed file logger with appropriate defaults.

Good encapsulation and reasonable default queue size. The queuing mechanism will help with performance by batching writes.


85-124: Solid daily rotation implementation.

Good error handling for missing files and appropriate date comparison logic. The rotated filename format with ISO date is clear and sortable.


125-156: Good utility methods for lifecycle and introspection.

The close method properly flushes pending writes, and the getter methods provide useful visibility into logger state.


157-201: Well-implemented singleton pattern with lazy loading.

Good handling of async initialization and race conditions by storing the Promise. The reset function will be valuable for testing.

flow-service/src/config/resolution/service-config-resolver.ts (2)

1-24: Good modularization with graph-based configuration approach.

The import changes reflect a cleaner separation of concerns with dedicated modules for loading, validation, and access. Enhanced error handling with LogContext improves observability.


89-142: Well-structured CLI option conversion.

The function properly handles the transformation from flat CLI options to the nested configuration structure with appropriate JSON-LD type annotations.

flow-core/src/utils/logger/error-handlers.ts (3)

1-15: Clean setup with appropriate logger choice.

Good choice using the enhanced logger for error handling to support Error object logging.


16-86: Robust error handling with comprehensive context capture.

Excellent defensive programming with unknown error type and fallback console logging. The error context extraction covers all necessary details.


402-466: Excellent utility functions for consistent error handling.

The withErrorHandling wrapper and createContextualErrorHandler factory promote consistent error handling patterns across the codebase. Good use of context merging.

flow-service/src/utils/service-logger.ts (3)

1-28: Well-structured service context with appropriate defaults.

Good use of environment variables with fallbacks. The unique instance ID generation helps with distributed tracing.


59-173: Comprehensive set of context-specific logger factories.

Excellent collection of factory functions covering all major service operations. Each provides appropriate contextual information for effective log correlation and debugging.


175-192: Clean utility functions and exports.

Good separation between the configured logger instance and utility functions. The default export provides convenient access.

flow-service/src/config/config-types.ts (1)

82-84: Verified: defaultAttributedTo is now a string with no residual object usage
All active references to this property have been updated to expect a string:

  • flow-service/src/config/config-types.ts
    'fsvc:defaultAttributedTo'?: string
    'conf:defaultAttributedTo'?: string
  • flow-service/src/services/metadata-composer.ts
    • The previous config.defaultAttributedTo line is commented out and replaced by a hard-coded URI, so no code treats it as an object.
  • Ripgrep search confirmed no un-commented TypeScript or JSON references expecting an object.

Please ensure any external configuration files are updated to supply a string (e.g. a URI) instead of the former object format.

flow-core/src/utils/logger/formatters.ts (1)

112-152: Well-structured console formatting with environment awareness

The console formatting function properly adapts output based on the environment, providing colorized output in development and structured JSON in production. The context summarization is concise and informative.

flow-service/src/config/index.ts (1)

90-109: Excellent error handling implementation

The refactored createServiceConfig function properly handles errors with comprehensive context information, making debugging easier. The use of structured LogContext and the handleCaughtError utility is a best practice.

Comment on lines +77 to +95
return createLogger(
{
enableConsole: true,
enableFile: true,
enableSentry: true,
serviceContext: {
serviceName: appName,
serviceVersion: appVersion || 'unknown',
environment: Deno.env.get('DENO_ENV') || 'development',
},
},
{
serviceContext: {
serviceName: appName,
serviceVersion: appVersion || 'unknown',
environment: Deno.env.get('DENO_ENV') || 'development',
},
},
);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove redundant serviceContext configuration.

Both factory functions pass serviceContext twice - once in the config parameter and once in the baseContext parameter. This duplication appears unnecessary unless the logger implementation specifically requires it in both places.

 export function createDefaultLogger(
   appName: string,
   appVersion?: string,
 ): StructuredLogger {
   return createLogger(
     {
       enableConsole: true,
       enableFile: true,
       enableSentry: true,
       serviceContext: {
         serviceName: appName,
         serviceVersion: appVersion || 'unknown',
         environment: Deno.env.get('DENO_ENV') || 'development',
       },
-    },
-    {
-      serviceContext: {
-        serviceName: appName,
-        serviceVersion: appVersion || 'unknown',
-        environment: Deno.env.get('DENO_ENV') || 'development',
-      },
     },
   );
 }

Apply the same change to createDefaultEnhancedLogger.

Also applies to: 108-126

🤖 Prompt for AI Agents
In flow-core/src/utils/logger/index.ts around lines 77 to 95 and 108 to 126, the
serviceContext object is redundantly passed in both the config and baseContext
parameters of the createLogger function. Remove the duplicate serviceContext
from the baseContext parameter, keeping it only in the config parameter to avoid
unnecessary duplication. Apply the same removal of redundant serviceContext in
the createDefaultEnhancedLogger function as well.

serviceName: appName,
serviceVersion: appVersion || 'unknown',
environment: Deno.env.get('DENO_ENV') || 'development',
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use consistent environment variable naming.

The code uses DENO_ENV while other parts of the codebase use FLOW_ENV (as mentioned in the formatters.ts snippet). This inconsistency could lead to configuration issues.

-        environment: Deno.env.get('DENO_ENV') || 'development',
+        environment: Deno.env.get('FLOW_ENV') || 'development',

Apply this change to all four occurrences in both factory functions.

Also applies to: 93-93, 116-116, 123-123

🤖 Prompt for AI Agents
In flow-core/src/utils/logger/index.ts at lines 86, 93, 116, and 123, replace
all occurrences of the environment variable name DENO_ENV with FLOW_ENV to
maintain consistent naming across the codebase. Update both factory functions
accordingly to ensure configuration uses FLOW_ENV uniformly.

Comment on lines +44 to +72
console.log(`🔧 Sentry enabled in config: ${sentryEnabled}`);

if (sentryEnabled && !sentryInitialized) {
console.log(`🔧 Initializing Sentry...`);
try {
Sentry.init({
dsn: sentryDsn,
environment: config?.environment || (isDevelopment ? 'development' : 'production'),
debug: config?.debug ?? isDevelopment,
tracesSampleRate: config?.tracesSampleRate ?? (isDevelopment ? 1.0 : 0.1),
release: config?.release || Deno.env.get('FLOW_VERSION'),
// Enable logs to be sent to Sentry (experimental feature)
_experiments: {
enableLogs: config?.enableLogs ?? true
},
});
sentryInitialized = true;
console.log(`🔧 DEBUG: Sentry initialized successfully`);
} catch (error) {
// Use console.error here to avoid circular dependency with error handlers
console.error(`🔧 ERROR: Failed to initialize Sentry: ${error}`);
console.error(`🔧 ERROR: Sentry will remain disabled`);
}
} else if (Deno.env.get('FLOW_SENTRY_ENABLED') !== 'true') {
console.log(`🔧 Sentry disabled - FLOW_SENTRY_ENABLED is not 'true'`);
} else if (!sentryDsn) {
console.log(`🔧 Sentry disabled - no DSN provided`);
} else {
console.log(`🔧 Sentry already initialized, skipping`);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace console.log with proper logging mechanism

The initialization function uses console.log statements for debugging output. These should be replaced with the structured logger to maintain consistency and allow proper log level control.

Consider using the structured logger instead of console.log for initialization messages. This would allow proper log level control and consistent formatting across the application.

-  console.log(`🔧 Sentry enabled in config: ${sentryEnabled}`);
+  // Use structured logger once available
+  // logger.debug('Sentry enabled in config', { sentryEnabled });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log(`🔧 Sentry enabled in config: ${sentryEnabled}`);
if (sentryEnabled && !sentryInitialized) {
console.log(`🔧 Initializing Sentry...`);
try {
Sentry.init({
dsn: sentryDsn,
environment: config?.environment || (isDevelopment ? 'development' : 'production'),
debug: config?.debug ?? isDevelopment,
tracesSampleRate: config?.tracesSampleRate ?? (isDevelopment ? 1.0 : 0.1),
release: config?.release || Deno.env.get('FLOW_VERSION'),
// Enable logs to be sent to Sentry (experimental feature)
_experiments: {
enableLogs: config?.enableLogs ?? true
},
});
sentryInitialized = true;
console.log(`🔧 DEBUG: Sentry initialized successfully`);
} catch (error) {
// Use console.error here to avoid circular dependency with error handlers
console.error(`🔧 ERROR: Failed to initialize Sentry: ${error}`);
console.error(`🔧 ERROR: Sentry will remain disabled`);
}
} else if (Deno.env.get('FLOW_SENTRY_ENABLED') !== 'true') {
console.log(`🔧 Sentry disabled - FLOW_SENTRY_ENABLED is not 'true'`);
} else if (!sentryDsn) {
console.log(`🔧 Sentry disabled - no DSN provided`);
} else {
console.log(`🔧 Sentry already initialized, skipping`);
// Use structured logger once available
// logger.debug('Sentry enabled in config', { sentryEnabled });
if (sentryEnabled && !sentryInitialized) {
console.log(`🔧 Initializing Sentry...`);
try {
Sentry.init({
dsn: sentryDsn,
environment: config?.environment || (isDevelopment ? 'development' : 'production'),
debug: config?.debug ?? isDevelopment,
tracesSampleRate: config?.tracesSampleRate ?? (isDevelopment ? 1.0 : 0.1),
release: config?.release || Deno.env.get('FLOW_VERSION'),
// Enable logs to be sent to Sentry (experimental feature)
_experiments: {
enableLogs: config?.enableLogs ?? true
},
});
sentryInitialized = true;
console.log(`🔧 DEBUG: Sentry initialized successfully`);
} catch (error) {
// Use console.error here to avoid circular dependency with error handlers
console.error(`🔧 ERROR: Failed to initialize Sentry: ${error}`);
console.error(`🔧 ERROR: Sentry will remain disabled`);
}
} else if (Deno.env.get('FLOW_SENTRY_ENABLED') !== 'true') {
console.log(`🔧 Sentry disabled - FLOW_SENTRY_ENABLED is not 'true'`);
} else if (!sentryDsn) {
console.log(`🔧 Sentry disabled - no DSN provided`);
} else {
console.log(`🔧 Sentry already initialized, skipping`);
🤖 Prompt for AI Agents
In flow-core/src/utils/logger/sentry-logger.ts between lines 44 and 72, replace
all console.log calls used for Sentry initialization status messages with the
structured logger used elsewhere in the application. This ensures consistent log
formatting and enables proper log level control. Also replace console.error
calls with the structured logger's error method to maintain uniform error
handling and avoid direct console usage.

Comment on lines +55 to +58
// Enable logs to be sent to Sentry (experimental feature)
_experiments: {
enableLogs: config?.enableLogs ?? true
},
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify experimental feature stability

The code enables an experimental Sentry feature (enableLogs). Experimental features may change or be removed in future versions.


🌐 Web query:

What is the current status of the Sentry _experiments.enableLogs feature and is it stable for production use?

💡 Result:

Sentry's _experiments.enableLogs feature, which enables structured logging, has evolved over time. Initially introduced as an experimental feature, it has since been integrated into the main SDK with a more stable configuration.

Current Status:

As of version 9.41.0, the enableLogs feature is no longer under the _experiments namespace. It has been moved to the top-level configuration, indicating a more stable and production-ready status. (gitlab.com)

Stability for Production Use:

The transition from _experiments.enableLogs to enableLogs suggests that the feature is now considered stable for production environments. Sentry's official documentation and recent releases support this, indicating that the structured logging feature is ready for use in production settings. (docs.sentry.dev)

Implementation:

To enable structured logging in your Sentry configuration, you can initialize the SDK as follows:

Sentry.init({
  dsn: 'YOUR_PUBLIC_DSN',
  enableLogs: true,
});

This setup allows you to send, view, and query logs within Sentry, providing a unified debugging experience alongside error and performance monitoring. (docs.sentry.dev)

In summary, the enableLogs feature has been integrated into Sentry's main SDK and is now stable for production use, offering enhanced logging capabilities for your applications.

Citations:


Update Sentry logging configuration to use the stable enableLogs option

Sentry has promoted enableLogs out of the _experiments namespace as of v9.41.0, so you no longer need to pass it under _experiments. Please update your initializer accordingly.

• File: flow-core/src/utils/logger/sentry-logger.ts
Replace the _experiments block with a top-level enableLogs setting.

Suggested diff:

--- a/flow-core/src/utils/logger/sentry-logger.ts
+++ b/flow-core/src/utils/logger/sentry-logger.ts
@@ lines 55-58
-        // Enable logs to be sent to Sentry (experimental feature)
-        _experiments: {
-          enableLogs: config?.enableLogs ?? true
-        },
+        // Enable structured logs in Sentry (now stable in SDK ≥9.41.0)
+        enableLogs: config?.enableLogs ?? true,

This aligns with the current Sentry SDK usage:

Sentry.init({
  dsn: 'YOUR_PUBLIC_DSN',
  enableLogs: true,  // production-ready
});

docs.sentry.dev

🤖 Prompt for AI Agents
In flow-core/src/utils/logger/sentry-logger.ts around lines 55 to 58, the Sentry
initialization incorrectly places the enableLogs option inside the _experiments
object. Remove the _experiments block and move enableLogs to be a top-level
property in the Sentry.init configuration object, setting it directly to
config?.enableLogs or true as default.

Comment on lines +46 to +105
async debug(
message: string,
context?: LogContext,
meta?: Record<string, unknown>,
): Promise<void> {
if (!shouldLog('DEBUG')) return;
const mergedContext = this.mergeContexts(context, meta);
await this.writeToAllChannels('DEBUG', message, mergedContext);
}

/**
* Log informational messages
*/
async info(
message: string,
context?: LogContext,
meta?: Record<string, unknown>,
): Promise<void> {
if (!shouldLog('INFO')) return;
const mergedContext = this.mergeContexts(context, meta);
await this.writeToAllChannels('INFO', message, mergedContext);
}

/**
* Log warning messages
*/
async warn(
message: string,
context?: LogContext,
meta?: Record<string, unknown>,
): Promise<void> {
if (!shouldLog('WARN')) return;
const mergedContext = this.mergeContexts(context, meta);
await this.writeToAllChannels('WARN', message, mergedContext);
}

/**
* Log error messages
*/
async error(
message: string,
context?: LogContext,
meta?: Record<string, unknown>,
): Promise<void> {
if (!shouldLog('ERROR')) return;
const mergedContext = this.mergeContexts(context, meta);
await this.writeToAllChannels('ERROR', message, mergedContext);
}

/**
* Log critical error messages
*/
async critical(
message: string,
context?: LogContext,
meta?: Record<string, unknown>,
): Promise<void> {
const mergedContext = this.mergeContexts(context, meta);
await this.writeToAllChannels('CRITICAL', message, mergedContext);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix async/sync method signature mismatch with interface.

The logging methods are declared as async and return Promise<void>, but according to the StructuredLogger interface in types.ts, they should return void. This mismatch could cause TypeScript compilation errors.

Either update the interface to reflect async methods or make these methods synchronous by handling async operations internally without awaiting.

🤖 Prompt for AI Agents
In flow-core/src/utils/logger/structured-logger.ts between lines 46 and 105, the
logging methods are declared async and return Promise<void>, but the
StructuredLogger interface expects them to return void, causing a type mismatch.
To fix this, either update the StructuredLogger interface in types.ts to have
these methods return Promise<void> to match the async implementation, or
refactor these methods to be synchronous by removing async/await and handling
any asynchronous operations internally without returning a Promise.

Comment on lines +84 to +123
export interface StructuredLogger {
/**
* Log debug information
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
debug(message: string, context?: LogContext, meta?: Record<string, unknown>): void;

/**
* Log informational messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
info(message: string, context?: LogContext, meta?: Record<string, unknown>): void;

/**
* Log warning messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
warn(message: string, context?: LogContext, meta?: Record<string, unknown>): void;

/**
* Log error messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
error(message: string, context?: LogContext, meta?: Record<string, unknown>): void;

/**
* Log critical error messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
critical(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Update StructuredLogger interface to reflect async implementation.

The interface methods are defined as returning void, but according to the implementation in structured-logger.ts, these methods are async and return Promise<void>. This type mismatch will cause issues when using the logger.

 export interface StructuredLogger {
   /**
    * Log debug information
    * @param message - The log message
    * @param context - Optional logging context
    * @param meta - Additional metadata
    */
-  debug(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
+  debug(message: string, context?: LogContext, meta?: Record<string, unknown>): Promise<void>;

   /**
    * Log informational messages
    * @param message - The log message
    * @param context - Optional logging context
    * @param meta - Additional metadata
    */
-  info(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
+  info(message: string, context?: LogContext, meta?: Record<string, unknown>): Promise<void>;

   /**
    * Log warning messages
    * @param message - The log message
    * @param context - Optional logging context
    * @param meta - Additional metadata
    */
-  warn(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
+  warn(message: string, context?: LogContext, meta?: Record<string, unknown>): Promise<void>;

   /**
    * Log error messages
    * @param message - The log message
    * @param context - Optional logging context
    * @param meta - Additional metadata
    */
-  error(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
+  error(message: string, context?: LogContext, meta?: Record<string, unknown>): Promise<void>;

   /**
    * Log critical error messages
    * @param message - The log message
    * @param context - Optional logging context
    * @param meta - Additional metadata
    */
-  critical(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
+  critical(message: string, context?: LogContext, meta?: Record<string, unknown>): Promise<void>;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface StructuredLogger {
/**
* Log debug information
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
debug(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
/**
* Log informational messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
info(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
/**
* Log warning messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
warn(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
/**
* Log error messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
error(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
/**
* Log critical error messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
critical(message: string, context?: LogContext, meta?: Record<string, unknown>): void;
export interface StructuredLogger {
/**
* Log debug information
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
debug(message: string, context?: LogContext, meta?: Record<string, unknown>): Promise<void>;
/**
* Log informational messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
info(message: string, context?: LogContext, meta?: Record<string, unknown>): Promise<void>;
/**
* Log warning messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
warn(message: string, context?: LogContext, meta?: Record<string, unknown>): Promise<void>;
/**
* Log error messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
error(message: string, context?: LogContext, meta?: Record<string, unknown>): Promise<void>;
/**
* Log critical error messages
* @param message - The log message
* @param context - Optional logging context
* @param meta - Additional metadata
*/
critical(message: string, context?: LogContext, meta?: Record<string, unknown>): Promise<void>;
}
🤖 Prompt for AI Agents
In flow-core/src/utils/logger/types.ts between lines 84 and 123, the
StructuredLogger interface methods are currently typed to return void, but the
actual implementation uses async methods returning Promise<void>. Update the
return types of all logging methods (debug, info, warn, error, critical) to
return Promise<void> to match the async implementation and avoid type
mismatches.

Comment on lines +52 to +53
const structuredMsg = formatStructuredMessage('DEBUG', 'Processing mesh nodes', complexContext);
console.log('Formatted structured message:', JSON.stringify(structuredMsg, null, 2));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove redundant JSON.stringify on already stringified JSON.

The formatStructuredMessage function already returns a JSON string. Calling JSON.stringify on it will double-encode the JSON, resulting in escaped quotes. To properly display the formatted JSON, parse it first:

 const structuredMsg = formatStructuredMessage('DEBUG', 'Processing mesh nodes', complexContext);
-console.log('Formatted structured message:', JSON.stringify(structuredMsg, null, 2));
+console.log('Formatted structured message:', JSON.stringify(JSON.parse(structuredMsg), null, 2));

Alternatively, just log the string directly:

-console.log('Formatted structured message:', JSON.stringify(structuredMsg, null, 2));
+console.log('Formatted structured message:', structuredMsg);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const structuredMsg = formatStructuredMessage('DEBUG', 'Processing mesh nodes', complexContext);
console.log('Formatted structured message:', JSON.stringify(structuredMsg, null, 2));
const structuredMsg = formatStructuredMessage('DEBUG', 'Processing mesh nodes', complexContext);
console.log('Formatted structured message:', JSON.stringify(JSON.parse(structuredMsg), null, 2));
🤖 Prompt for AI Agents
In flow-core/tests/integration/logger/formatters.test.ts at lines 52-53, the
code calls JSON.stringify on the result of formatStructuredMessage, which
already returns a JSON string, causing double encoding. Fix this by either
logging the string directly without JSON.stringify or by parsing the string
first with JSON.parse before logging to display the formatted JSON properly.

Comment on lines 31 to 36
readonly 'fsvc:logRotationInterval'?:
| 'daily'
| 'weekly'
| 'monthly'
| 'size-based';
| 'daily'
| 'weekly'
| 'monthly'
| 'size-based';
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify consistent naming convention for rotation intervals

The log rotation interval values use kebab-case format. Ensure this naming convention is consistently handled throughout the codebase, especially in any parsing or validation logic.


🏁 Script executed:

#!/bin/bash
# Description: Check for consistent handling of log rotation interval values

# Search for references to log rotation intervals
rg -A 3 "logRotationInterval|rotation.*interval" --type ts

Length of output: 1433


Include all interval options in loader and validate inputs

The union in config-types.ts now includes size-based, but the env-loader only asserts
'daily' | 'weekly' | 'monthly'. Update it to cover size-based, and add a runtime check to reject invalid values.

• File: flow-service/src/config/loaders/env-loader.ts
– Change the type assertion to:
ts fileChannel['fsvc:logRotationInterval'] = interval as | 'daily' | 'weekly' | 'monthly' | 'size-based';
– Before assigning, verify:
ts const validIntervals = ['daily', 'weekly', 'monthly', 'size-based'] as const; if (!validIntervals.includes(interval as any)) { throw new Error( `Invalid logRotationInterval "${interval}". Must be one of ${validIntervals.join(', ')}` ); }
• File: flow-service/src/config/defaults.ts
– Consider allowing other defaults beyond daily, or document why only daily is used.

This ensures the kebab-case convention (including size-based) is consistently parsed and validated.

🤖 Prompt for AI Agents
In flow-service/src/config/loaders/env-loader.ts around lines where
fsvc:logRotationInterval is assigned, update the type assertion to include
'size-based' along with 'daily', 'weekly', and 'monthly'. Before assigning, add
a runtime validation that checks if the interval value is one of these valid
options; if not, throw an error indicating the invalid value and listing the
allowed options. Also, review flow-service/src/config/defaults.ts to either
allow other default values beyond 'daily' or add documentation explaining why
'daily' is the only default used.

Comment on lines +29 to +52
/**
* Service-specific logger configuration
*/
const SERVICE_LOGGER_CONFIG: LoggerConfig = {
enableConsole: true,
enableFile: Deno.env.get('FLOW_LOG_FILE_ENABLED') === 'true',
enableSentry: Deno.env.get('FLOW_SENTRY_ENABLED') === 'true',

fileConfig: {
logDir: Deno.env.get('FLOW_LOG_DIR') || './logs',
maxFileSize: parseInt(Deno.env.get('FLOW_LOG_MAX_FILE_SIZE') || '10485760'), // 10MB
maxFiles: parseInt(Deno.env.get('FLOW_LOG_MAX_FILES') || '5'),
rotateDaily: Deno.env.get('FLOW_LOG_ROTATE_DAILY') === 'true',
},

sentryConfig: {
dsn: Deno.env.get('FLOW_SENTRY_DSN'),
environment: Deno.env.get('FLOW_ENV') || 'development',
release: Deno.env.get('FLOW_VERSION'),
sampleRate: parseFloat(Deno.env.get('FLOW_SENTRY_SAMPLE_RATE') || '1.0'),
},

serviceContext: SERVICE_CONTEXT,
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add validation for numeric environment variable parsing.

The parseInt and parseFloat calls could produce NaN values if environment variables contain invalid values, which could cause runtime errors.

 const SERVICE_LOGGER_CONFIG: LoggerConfig = {
   enableConsole: true,
   enableFile: Deno.env.get('FLOW_LOG_FILE_ENABLED') === 'true',
   enableSentry: Deno.env.get('FLOW_SENTRY_ENABLED') === 'true',
 
   fileConfig: {
     logDir: Deno.env.get('FLOW_LOG_DIR') || './logs',
-    maxFileSize: parseInt(Deno.env.get('FLOW_LOG_MAX_FILE_SIZE') || '10485760'), // 10MB
-    maxFiles: parseInt(Deno.env.get('FLOW_LOG_MAX_FILES') || '5'),
+    maxFileSize: parseInt(Deno.env.get('FLOW_LOG_MAX_FILE_SIZE') || '10485760') || 10485760, // 10MB
+    maxFiles: parseInt(Deno.env.get('FLOW_LOG_MAX_FILES') || '5') || 5,
     rotateDaily: Deno.env.get('FLOW_LOG_ROTATE_DAILY') === 'true',
   },
 
   sentryConfig: {
     dsn: Deno.env.get('FLOW_SENTRY_DSN'),
     environment: Deno.env.get('FLOW_ENV') || 'development',
     release: Deno.env.get('FLOW_VERSION'),
-    sampleRate: parseFloat(Deno.env.get('FLOW_SENTRY_SAMPLE_RATE') || '1.0'),
+    sampleRate: parseFloat(Deno.env.get('FLOW_SENTRY_SAMPLE_RATE') || '1.0') || 1.0,
   },
 
   serviceContext: SERVICE_CONTEXT,
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Service-specific logger configuration
*/
const SERVICE_LOGGER_CONFIG: LoggerConfig = {
enableConsole: true,
enableFile: Deno.env.get('FLOW_LOG_FILE_ENABLED') === 'true',
enableSentry: Deno.env.get('FLOW_SENTRY_ENABLED') === 'true',
fileConfig: {
logDir: Deno.env.get('FLOW_LOG_DIR') || './logs',
maxFileSize: parseInt(Deno.env.get('FLOW_LOG_MAX_FILE_SIZE') || '10485760'), // 10MB
maxFiles: parseInt(Deno.env.get('FLOW_LOG_MAX_FILES') || '5'),
rotateDaily: Deno.env.get('FLOW_LOG_ROTATE_DAILY') === 'true',
},
sentryConfig: {
dsn: Deno.env.get('FLOW_SENTRY_DSN'),
environment: Deno.env.get('FLOW_ENV') || 'development',
release: Deno.env.get('FLOW_VERSION'),
sampleRate: parseFloat(Deno.env.get('FLOW_SENTRY_SAMPLE_RATE') || '1.0'),
},
serviceContext: SERVICE_CONTEXT,
};
/**
* Service-specific logger configuration
*/
const SERVICE_LOGGER_CONFIG: LoggerConfig = {
enableConsole: true,
enableFile: Deno.env.get('FLOW_LOG_FILE_ENABLED') === 'true',
enableSentry: Deno.env.get('FLOW_SENTRY_ENABLED') === 'true',
fileConfig: {
logDir: Deno.env.get('FLOW_LOG_DIR') || './logs',
maxFileSize: parseInt(Deno.env.get('FLOW_LOG_MAX_FILE_SIZE') || '10485760') || 10485760, // 10MB
maxFiles: parseInt(Deno.env.get('FLOW_LOG_MAX_FILES') || '5') || 5,
rotateDaily: Deno.env.get('FLOW_LOG_ROTATE_DAILY') === 'true',
},
sentryConfig: {
dsn: Deno.env.get('FLOW_SENTRY_DSN'),
environment: Deno.env.get('FLOW_ENV') || 'development',
release: Deno.env.get('FLOW_VERSION'),
sampleRate: parseFloat(Deno.env.get('FLOW_SENTRY_SAMPLE_RATE') || '1.0') || 1.0,
},
serviceContext: SERVICE_CONTEXT,
};
🤖 Prompt for AI Agents
In flow-service/src/utils/service-logger.ts between lines 29 and 52, the numeric
environment variables parsed with parseInt and parseFloat can result in NaN if
the input is invalid. Add validation checks after parsing these values to ensure
they are valid numbers; if not, fallback to default values to prevent runtime
errors. Implement this validation for maxFileSize, maxFiles, and sampleRate
fields in the SERVICE_LOGGER_CONFIG object.

djradon added 3 commits August 3, 2025 22:09
- Added `expandRelativeIds` function to expand relative IDs in JSON-LD objects based on a provided base IRI.
- Updated `jsonldToQuads` function to utilize `jsonld.toRDF` for converting JSON-LD to RDFJS quads.
- Modified `flow-service-config.jsonld` to adjust service configuration, including changes to ports and rights holders.
- Refactored `config-types.ts` to standardize property names and types across interfaces.
- Updated default service configurations in `defaults.ts` to reflect new structure and IDs.
- Enhanced environment variable loading in `env-loader.ts` to include new service configuration properties.
- Implemented dynamic URI handling in `quadstore-loader.ts` for loading platform defaults and input configurations.
- Adjusted service configuration resolution logic in `service-config-resolver.ts` to utilize updated loading functions.
- Cleaned up service URI building logic in `service-uri-builder.ts` to simplify graph URI construction.
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: 3

♻️ Duplicate comments (1)
flow-service/src/config/loaders/quadstore-loader.ts (1)

11-17: Consider adding error handling for platform defaults loading.

The function should handle potential errors when loading platform defaults, as failures here could prevent the entire configuration system from initializing.

 export async function loadPlatformServiceDefaults(): Promise<void> {
-
-  const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.platformServiceDefaults);
-  const expandedPlatformServiceDefaults = expandRelativeIds(PLATFORM_SERVICE_DEFAULTS, uri);
-  // use the Service URI for the graph name
-  await createNewGraphFromJsonLd(expandedPlatformServiceDefaults, { graphName: uri });
+  try {
+    const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.platformServiceDefaults);
+    const expandedPlatformServiceDefaults = expandRelativeIds(PLATFORM_SERVICE_DEFAULTS, uri);
+    // use the Service URI for the graph name
+    await createNewGraphFromJsonLd(expandedPlatformServiceDefaults, { graphName: uri });
+  } catch (error) {
+    throw new Error(`Failed to load platform service defaults: ${error instanceof Error ? error.message : String(error)}`);
+  }
 }
🧹 Nitpick comments (7)
flow-core/src/utils/rdfjs-utils.ts (1)

14-16: Clean up blank lines and confirm jsonld.toRDF return type

Removed two empty lines after the function signature and added a note to ensure the return value really is an array of RDF.Quad.

• Apply this diff to remove the blank lines:

 ): Promise<RDF.Quad[]> {
-
-
   const quads = await jsonld.toRDF(inputJsonLd) as RDF.Quad[];

• Verify that jsonld.toRDF(inputJsonLd) actually returns RDF.Quad[] (per the jsonld.js API), or adjust the call/options (e.g. specify {format: 'application/n-quads'} or update the type definitions) so that the assertion is guaranteed safe.

flow-service/src/utils/service-uri-builder.ts (1)

31-35: Consider handling trailing slashes more carefully.

The function always appends a trailing slash, which might not be appropriate for all paths (e.g., file paths or query parameters).

Consider making trailing slash addition conditional:

 export function buildServiceUri(config: ServiceUriConfig, path: string): string {
   const baseUri = buildServiceBaseUri(config);
   const cleanPath = path.replace(/^\/+/, '');
-  return `${baseUri}${cleanPath}/`;
+  // Only add trailing slash if path doesn't end with one and doesn't contain query/fragment
+  const needsTrailingSlash = cleanPath && !cleanPath.endsWith('/') && 
+    !cleanPath.includes('?') && !cleanPath.includes('#');
+  return `${baseUri}${cleanPath}${needsTrailingSlash ? '/' : ''}`;
 }
flow-service/src/config/loaders/quadstore-loader.ts (1)

69-76: Remove console.log and clean up empty lines.

The function contains a console.log statement that should use proper logging, and has unnecessary empty lines.

     if (exists === 0) {
-      console.log(`platform quad copied: ${q.subject.value} ${q.predicate.value} ${q.object.value} in graph ${mergedUri}`);
-
       await store.put(df.quad(q.subject, q.predicate, q.object, df.namedNode(mergedUri)));
     }
   }
-
-
 }

If logging is needed, consider using the service logger instead of console.log.

flow-service/src/config/resolution/service-config-resolver.ts (2)

37-37: Remove commented debugging code.

The commented console.log statement should be removed.

     // Load environment config
     const envConfig = loadEnvConfig();
-    //console.log(envConfig)
     // Load file config if specified

67-69: Track TODO for loading mesh node configuration.

The TODO comment indicates missing functionality for loading input mesh root node configuration.

Would you like me to create an issue to track the implementation of mesh root node configuration loading?

flow-service/src/config/config-types.ts (1)

60-61: Clarify or complete the TODO for type renaming.

The TODO comment is incomplete. What should MeshRootNodeConfig be renamed to?

Would you like me to help determine an appropriate name based on the type's usage pattern, or should this TODO be removed if no longer relevant?

flow-service/src/config/index.ts (1)

10-20: Consider using 'as const' for better type safety

The graph names constant would benefit from const assertion to ensure type safety and prevent accidental modifications.

-export const CONFIG_GRAPH_NAMES = {
+export const CONFIG_GRAPH_NAMES = {
   platformServiceDefaults: 'platformServiceDefaults',
   platformImplicitMeshRootNodeConfig: 'platformImplicitMeshRootNodeConfig',
   inputServiceConfig: 'inputServiceConfig',
   inputMeshRootNodeConfig: 'inputMeshRootNodeConfig',
   mergedServiceConfig: 'mergedServiceConfig',
-}
+} as const;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d7a11e and 8942f98.

📒 Files selected for processing (16)
  • flow-core/src/utils/quadstore-utils.ts (1 hunks)
  • flow-core/src/utils/rdfjs-utils.ts (1 hunks)
  • flow-service/flow-service-config.jsonld (1 hunks)
  • flow-service/main.ts (6 hunks)
  • flow-service/src/config/config-types.ts (1 hunks)
  • flow-service/src/config/defaults.ts (2 hunks)
  • flow-service/src/config/index.ts (2 hunks)
  • flow-service/src/config/loaders/env-loader.ts (12 hunks)
  • flow-service/src/config/loaders/quadstore-loader.ts (1 hunks)
  • flow-service/src/config/resolution/service-config-accessor.ts (1 hunks)
  • flow-service/src/config/resolution/service-config-loader.ts (1 hunks)
  • flow-service/src/config/resolution/service-config-resolver.ts (2 hunks)
  • flow-service/src/config/resolution/service-config-validator.ts (1 hunks)
  • flow-service/src/service-constants.ts (1 hunks)
  • flow-service/src/utils/service-log-context.ts (1 hunks)
  • flow-service/src/utils/service-uri-builder.ts (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • flow-service/src/service-constants.ts
  • flow-service/src/utils/service-log-context.ts
  • flow-service/flow-service-config.jsonld
🚧 Files skipped from review as they are similar to previous changes (7)
  • flow-service/src/config/resolution/service-config-validator.ts
  • flow-service/main.ts
  • flow-service/src/config/resolution/service-config-loader.ts
  • flow-service/src/config/resolution/service-config-accessor.ts
  • flow-service/src/config/defaults.ts
  • flow-core/src/utils/quadstore-utils.ts
  • flow-service/src/config/loaders/env-loader.ts
🔇 Additional comments (11)
flow-service/src/utils/service-uri-builder.ts (2)

9-26: LGTM! Well-structured URI configuration and builder.

The interface and base URI builder correctly handle default ports for HTTP/HTTPS protocols.


41-73: LGTM! Well-implemented singleton with proper state management.

The singleton correctly manages configuration state, implements caching for performance, and provides clear error messages when accessed before initialization.

flow-service/src/config/resolution/service-config-resolver.ts (1)

106-155: LGTM! Well-structured CLI options conversion.

The function correctly maps all CLI options to the configuration format, including proper validation of log levels and nested configuration object construction.

flow-service/src/config/config-types.ts (2)

171-187: LGTM! Well-designed error classes.

The error classes properly extend Error, use descriptive names, and support error chaining through the cause property. The ConfigValidationError appropriately extends ConfigError with additional validation error details.


31-36: Env-loader supports the new “size-based” option

Env-loader’s assignment now casts interval to all four variants—including "size-based"—so no further changes are needed.

flow-service/src/config/index.ts (6)

8-9: LGTM!

The import aligns with the new structured logging system.


23-36: LGTM!

Type exports properly reflect the new "mesh root node" terminology and modular structure.


39-39: LGTM!

Error class exports support proper typed error handling.


60-65: LGTM!

Function renames are consistent with the new mesh root node terminology and follow proper naming conventions.


72-75: LGTM!

The modular exports properly separate validation and configuration access concerns.


80-108: Error handling utilities verified

  • handleCaughtError is exported as an async function in flow-core/src/utils/logger/error-handlers.ts (line 98).
  • LogContext interface is defined and exported in flow-core/src/utils/logger/types.ts (line 11).

No further actions required. Approving the changes.

Comment on lines +42 to +44
if (typeof obj["@id"] === "string" && !obj["@id"].startsWith("http")) {
obj["@id"] = baseIRI + obj["@id"];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve URL validation for @id fields.

The current check !obj["@id"].startsWith("http") is too broad and could match invalid schemes like "httpx://". Consider checking for valid URL schemes more precisely.

Apply this diff to improve the validation:

-      if (typeof obj["@id"] === "string" && !obj["@id"].startsWith("http")) {
+      if (typeof obj["@id"] === "string" && !obj["@id"].startsWith("http://") && !obj["@id"].startsWith("https://")) {
         obj["@id"] = baseIRI + obj["@id"];
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (typeof obj["@id"] === "string" && !obj["@id"].startsWith("http")) {
obj["@id"] = baseIRI + obj["@id"];
}
if (
typeof obj["@id"] === "string" &&
!obj["@id"].startsWith("http://") &&
!obj["@id"].startsWith("https://")
) {
obj["@id"] = baseIRI + obj["@id"];
}
🤖 Prompt for AI Agents
In flow-core/src/utils/rdfjs-utils.ts around lines 42 to 44, the current check
for obj["@id"] uses startsWith("http"), which can incorrectly match invalid
schemes like "httpx://". To fix this, replace the check with a more precise
validation that ensures obj["@id"] starts specifically with "http://" or
"https://". Update the condition to verify the URL scheme explicitly before
deciding to prepend baseIRI.

Comment on lines +19 to +23
export async function loadPlatformImplicitMeshRootNodeConfig(): Promise<void> {
const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.platformImplicitMeshRootNodeConfig);
const expandedPlatformNodeDefaults = expandRelativeIds(PLATFORM_NODE_DEFAULTS, uri);
await createNewGraphFromJsonLd(expandedPlatformNodeDefaults, { graphName: uri });
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for platform mesh root node config loading.

Similar to the previous function, this should handle potential errors during loading.

 export async function loadPlatformImplicitMeshRootNodeConfig(): Promise<void> {
-  const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.platformImplicitMeshRootNodeConfig);
-  const expandedPlatformNodeDefaults = expandRelativeIds(PLATFORM_NODE_DEFAULTS, uri);
-  await createNewGraphFromJsonLd(expandedPlatformNodeDefaults, { graphName: uri });
+  try {
+    const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.platformImplicitMeshRootNodeConfig);
+    const expandedPlatformNodeDefaults = expandRelativeIds(PLATFORM_NODE_DEFAULTS, uri);
+    await createNewGraphFromJsonLd(expandedPlatformNodeDefaults, { graphName: uri });
+  } catch (error) {
+    throw new Error(`Failed to load platform mesh root node config: ${error instanceof Error ? error.message : String(error)}`);
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function loadPlatformImplicitMeshRootNodeConfig(): Promise<void> {
const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.platformImplicitMeshRootNodeConfig);
const expandedPlatformNodeDefaults = expandRelativeIds(PLATFORM_NODE_DEFAULTS, uri);
await createNewGraphFromJsonLd(expandedPlatformNodeDefaults, { graphName: uri });
}
export async function loadPlatformImplicitMeshRootNodeConfig(): Promise<void> {
try {
const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.platformImplicitMeshRootNodeConfig);
const expandedPlatformNodeDefaults = expandRelativeIds(PLATFORM_NODE_DEFAULTS, uri);
await createNewGraphFromJsonLd(expandedPlatformNodeDefaults, { graphName: uri });
} catch (error) {
throw new Error(`Failed to load platform mesh root node config: ${error instanceof Error ? error.message : String(error)}`);
}
}
🤖 Prompt for AI Agents
In flow-service/src/config/loaders/quadstore-loader.ts around lines 19 to 23,
the function loadPlatformImplicitMeshRootNodeConfig lacks error handling. Wrap
the existing code in a try-catch block to catch any errors during the loading
process, and log or handle the error appropriately to prevent unhandled
exceptions and improve reliability.

Comment on lines +28 to +34
export async function loadInputServiceConfig(inputConfig: ServiceConfigInput): Promise<void> {
//console.log(inputConfig);
const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.inputServiceConfig);
const expandedInputServiceConfig = expandRelativeIds(inputConfig, uri);
//console.log(expandedInputServiceConfig)
await createNewGraphFromJsonLd(expandedInputServiceConfig, { graphName: uri });
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove commented code and add error handling.

The function contains commented debugging code that should be removed, and lacks error handling.

 export async function loadInputServiceConfig(inputConfig: ServiceConfigInput): Promise<void> {
-  //console.log(inputConfig);
-  const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.inputServiceConfig);
-  const expandedInputServiceConfig = expandRelativeIds(inputConfig, uri);
-  //console.log(expandedInputServiceConfig)
-  await createNewGraphFromJsonLd(expandedInputServiceConfig, { graphName: uri });
+  try {
+    const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.inputServiceConfig);
+    const expandedInputServiceConfig = expandRelativeIds(inputConfig, uri);
+    await createNewGraphFromJsonLd(expandedInputServiceConfig, { graphName: uri });
+  } catch (error) {
+    throw new Error(`Failed to load input service config: ${error instanceof Error ? error.message : String(error)}`);
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function loadInputServiceConfig(inputConfig: ServiceConfigInput): Promise<void> {
//console.log(inputConfig);
const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.inputServiceConfig);
const expandedInputServiceConfig = expandRelativeIds(inputConfig, uri);
//console.log(expandedInputServiceConfig)
await createNewGraphFromJsonLd(expandedInputServiceConfig, { graphName: uri });
}
export async function loadInputServiceConfig(inputConfig: ServiceConfigInput): Promise<void> {
try {
const uri = getCurrentServiceUri(CONFIG_GRAPH_NAMES.inputServiceConfig);
const expandedInputServiceConfig = expandRelativeIds(inputConfig, uri);
await createNewGraphFromJsonLd(expandedInputServiceConfig, { graphName: uri });
} catch (error) {
throw new Error(`Failed to load input service config: ${error instanceof Error ? error.message : String(error)}`);
}
}
🤖 Prompt for AI Agents
In flow-service/src/config/loaders/quadstore-loader.ts around lines 28 to 34,
remove the commented out console.log debugging statements and add proper error
handling to the async function loadInputServiceConfig. Wrap the existing code in
a try-catch block and handle any errors by logging or rethrowing them
appropriately to ensure failures are managed gracefully.

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: 0

🧹 Nitpick comments (3)
flow-service/src/config/resolution/service-config-resolver.ts (3)

4-4: Import organization: Consider grouping related imports.

The import for ServiceOptions is separated from other type imports. Consider grouping it with the type imports on lines 1-4 for better organization.

import type {
  ServiceConfigInput,
- ServiceOptions,
+  ServiceOptions,
} from '../config-types.ts';

23-23: Import placement: Move imports to the top of the file.

The import statement is placed after the function JSDoc comment, which is unconventional. Consider moving all imports to the top of the file for better readability and consistency.

import { createServiceLogContext } from '../../utils/service-log-context.ts';
import { serviceUriConfigManager, type ServiceUriConfig } from '../../utils/service-uri-builder.ts';
+import { loadPlatformServiceDefaults, loadInputServiceConfig, loadInputMeshRootNodeConfig, mergeServiceConfigGraphs } from '../loaders/quadstore-loader.ts';

/**
 * Asynchronously resolves the service configuration by merging CLI options, environment variables, configuration files, and environment-specific defaults in a defined precedence order.
 *
 * @param cliOptions - Optional CLI-provided service options to override other configuration sources
 * @throws ConfigError if configuration resolution fails or an unexpected error occurs
 */

-import { loadPlatformServiceDefaults, loadInputServiceConfig, loadInputMeshRootNodeConfig, mergeServiceConfigGraphs } from '../loaders/quadstore-loader.ts';

64-65: Address the TODO comment for mesh node config loading.

The TODO comment indicates incomplete implementation for loading input mesh root node config. This might be intentional for this PR, but should be tracked.

The TODO suggests that mesh root node config loading is not yet implemented. Would you like me to create a tracking issue for this feature or help implement the mesh node config loading logic?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8942f98 and 5046780.

📒 Files selected for processing (3)
  • flow-service/src/config/index.ts (2 hunks)
  • flow-service/src/config/loaders/quadstore-loader.ts (1 hunks)
  • flow-service/src/config/resolution/service-config-resolver.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • flow-service/src/config/loaders/quadstore-loader.ts
🔇 Additional comments (10)
flow-service/src/config/resolution/service-config-resolver.ts (4)

49-56: Early service URI config extraction and initialization looks correct.

The approach of extracting service URI configuration early and initializing the service URI config manager before Quadstore operations is well-designed. This ensures the service URI is available for any subsequent operations that might need it.


71-78: Enhanced error context creation is well-implemented.

The structured error context with operation, component, and config metadata provides excellent diagnostic information. This is a significant improvement over basic error handling.


108-110: New scheme support in CLI options conversion.

The addition of scheme support in the CLI options conversion aligns with the service URI configuration requirements. The implementation correctly handles the optional scheme parameter.


25-27: All callers updated to handle void return

The resolveServiceConfig function now returns void, and no callers expect a return value:

• flow-service/src/config/index.ts
• Line 25: await resolveServiceConfig(cliOptions);
• No assignments or usages of a returned value found

No further changes are needed.

flow-service/src/config/index.ts (6)

13-19: CONFIG_GRAPH_NAMES constant provides clear graph identification.

The named graph constants provide clear identification for different configuration graphs in Quadstore. This is a good practice for maintainability and debugging.


23-36: Type export reorganization improves clarity.

The updated type exports with more specific names like MeshRootNodeConfig and FlowServiceContext provide better semantic clarity than the previous generic names. This improves code readability and maintainability.


97-102: Enhanced error context in createServiceConfig is comprehensive.

The structured error context with operation, component, and metadata provides excellent diagnostic information. The inclusion of CLI options in the metadata will help with debugging configuration issues.


90-92: No breaking changes in createServiceConfig usages

I’ve verified all createServiceConfig( calls across the codebase and confirmed they simply await createServiceConfig(); without expecting a return value. The new singleton accessor pattern is in place and no callers assign or use its return. No further action required.


64-64: No internal callers of validateJsonLd found
I searched the entire repo for invocations of validateJsonLd and only found its definition and re-export—no internal call sites to update. The simplified signature won’t break anything here.

If this function is used by downstream consumers, please verify those external callers match the new one-arg signature.


72-74: Concurrency safety confirmed for singletonServiceConfigAccessor

The singletonServiceConfigAccessor only provides read-only getters against the shared Quadstore bundle (initialized once at startup). It does not mutate any state and relies on the SPARQL engine—which supports handling multiple simultaneous queries—for all its operations. You can safely ignore the original concurrency concern.

Likely an incorrect or invalid review comment.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Aug 5, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@djradon djradon merged commit 49e4eb3 into main Aug 5, 2025
0 of 2 checks passed
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.

1 participant