LearnNewsExamplesServices
Frontmatter
id14404
titleGraph-only tenantRepo config is invisible to pull-mode sync
stateClosed
labels
bugaiarchitecture
assigneesneo-gpt
createdAtJul 1, 2026, 7:19 PM
updatedAtJul 1, 2026, 11:53 PM
githubUrlhttps://github.com/neomjs/neo/issues/14404
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 1, 2026, 11:53 PM

Graph-only tenantRepo config is invisible to pull-mode sync

Closed v13.1.0/archive-v13-1-0-chunk-8 bugaiarchitecture
neo-gpt
neo-gpt commented on Jul 1, 2026, 7:19 PM

Context

A cloud-deployment empty-KB investigation exposed a resolver blind spot in the server-side pull path. The new deployment diagnostics are the right direction, but they can only report what TenantRepoSyncService.resolveTenantReposConfig() can see. Today that path delegates to KnowledgeBaseIngestionService.listConfiguredTenantRepos(), and that resolver only enumerates tenant IDs from keyed tiers: kb-config.yaml tenant keys plus aiConfig.tenantRepos[] defaults.

The current source explicitly records the limitation:

  • ai/services/knowledge-base/IngestionService.mjs documents that a tenant configured only through a KnowledgeBaseTenantConfig graph node is not enumerated.
  • test/playwright/unit/ai/services/knowledge-base/IngestionService.spec.mjs pins that behavior with the graph-only tenant exclusion case.
  • Cloud configuration docs describe KnowledgeBaseTenantConfig graph nodes as a live tier for tenant config, including tenantRepos.

Live latest-open sweep: checked the latest 20 open issues on 2026-07-01; no equivalent open ticket found. Duplicate sweep also checked graph-only tenant config tenantRepos listConfiguredTenantRepos kb-config; closest historical issue is closed #12145, which established the current tiered resolver shape. A2A in-flight sweep checked the latest 30 messages; no overlapping [lane-claim] or [lane-intent] was present.

The Problem

If a deployment stores tenantRepos only in KnowledgeBaseTenantConfig graph nodes, pull-mode sync can report zero configured repos even though repo config exists in the graph. That creates a bad operator diagnostic path:

  1. KB can be healthy and empty.
  2. Ingestion can be idle with no last run.
  3. Deployment state can say there are no configured tenant repos because the pull-mode resolver never discovered graph-only tenant IDs.
  4. Operators then chase scheduler, Git access, embedding, or Chroma problems before the real problem: the resolver's tenant discovery boundary.

This is especially sharp because setTenantConfig() already persists tenantRepos into KnowledgeBaseTenantConfig and the docs present that graph node as canonical runtime config. The old out-of-scope assumption no longer reads as a safe permanent limitation.

The Architectural Reality

  • TenantRepoSyncService.resolveTenantReposConfig() uses KnowledgeBaseIngestionService.listConfiguredTenantRepos(); it does not discover tenants itself.
  • listConfiguredTenantRepos() chooses the highest present tier per tenant: graph node > YAML bootstrap > aiConfig fallback.
  • The tier ordering is sound, but the tenant-ID seed set is incomplete for graph-only config because it is derived only from YAML keys and aiConfig.tenantRepos[] entries.
  • A naive raw kb-config:* graph scan is risky: the resolver comments intentionally cite RLS and avoiding raw node scans. The fix needs a sanctioned tenant-config discovery surface, not an ad hoc query that bypasses access boundaries.
  • Deployment diagnostics added by #14396 can only classify what this resolver returns; they should distinguish true no-config from graph-only config that cannot currently be enumerated, once the resolver exposes the distinction.

The Fix

Add an ADR-compatible, RLS-respecting way for pull-mode sync to enumerate graph-backed tenant config nodes when no YAML/default tier names the tenant.

Likely shape:

  • Add a KnowledgeBaseIngestionService/GraphService helper that lists KnowledgeBaseTenantConfig identities through an allowlisted, visibility-aware graph query or maintained tenant-config index.
  • Update listConfiguredTenantRepos() to include graph-only tenant config nodes in the tenant set without weakening the existing per-tenant winner semantics.
  • Preserve tenantRepos: [] as an explicit higher-tier disable for that tenant.
  • Update deployment diagnostics so tenantRepoSync.config can distinguish true no-configured-repos from graph-config discovery errors.
  • Replace or narrow the current graph-only exclusion test with coverage for graph-only discovery and RLS-safe failure behavior.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
KnowledgeBaseIngestionService.listConfiguredTenantRepos() ai/services/knowledge-base/IngestionService.mjs Enumerates effective tenantRepos for YAML, aiConfig, and graph-only tenant config nodes If graph discovery fails, return a bounded diagnostic error instead of silently treating the deployment as empty learn/agentos/cloud-deployment/Configuration.md, TenantIngestionModel.md, Troubleshooting.md Unit tests for graph-only config, explicit empty config, malformed config, and discovery failure
tenantRepoSync deployment diagnostics DeploymentStateBridgeService.collectTenantRepoSyncSnapshot() Reports config state based on the expanded resolver and distinguishes true empty config from discovery degradation status: degraded with stable reason code when discovery fails learn/agentos/cloud-deployment/Troubleshooting.md Deployment-state unit test covering graph-discovery failure summary

Decision Record impact

Aligned with ADR 0014 and ADR 0022. The lane remains a distinct cloud-deployable, heavy pull-ingestion task; this ticket fixes the config-discovery substrate feeding that lane. No ADR amendment is expected unless the RLS-safe graph discovery shape requires a new graph-query contract.

Acceptance Criteria

  • listConfiguredTenantRepos() includes tenant config nodes that exist only in the graph tier.
  • Existing per-tenant tier precedence remains unchanged: graph > YAML > aiConfig, winner chosen by tier presence, not array length.
  • A graph node with tenantRepos: [] still explicitly disables pull-mode for that tenant.
  • The implementation does not use an unrestricted raw graph scan that bypasses RLS/visibility intent.
  • Deployment diagnostics distinguish true no-config from tenant-config discovery failure or unreadable graph state.
  • Tests cover graph-only tenant repo config, explicit empty graph config, YAML/default precedence, malformed graph config, and discovery failure.
  • Cloud deployment docs are updated so operators know graph-only tenant config is supported, and what diagnostic status means when discovery fails.

Out of Scope

  • Changing the GitMirror credential boundary.
  • Changing tenant repo normalization semantics.
  • Re-pointing kbSync; pull-mode remains tenant-repo-sync.
  • Adding a new tenant-config write tool unless the discovery fix proves that such a tool is the missing sanctioned substrate.

Related

  • #12145 — closed resolver ticket that established the current keyed-tier behavior.
  • #14396 / PR #14398 — tenant-repo-sync deployment diagnostics.
  • #14402 / PR #14403 — source error-code provenance for GitMirror failures.
  • learn/agentos/cloud-deployment/Configuration.md
  • learn/agentos/cloud-deployment/TenantIngestionModel.md

Retrieval Hint: "graph-only tenantRepos listConfiguredTenantRepos KnowledgeBaseTenantConfig resolver no configured repos"

tobiu closed this issue on Jul 1, 2026, 11:53 PM
tobiu referenced in commit 2493b1c - "fix(ai): include graph-only tenant repos in pull sync (#14404) (#14405)" on Jul 1, 2026, 11:53 PM