decomposer: generate deliverable files for Define the normalized ingestion contract and pluggable source-connector interface for SCM, CMS, and other content sources.; Implement a GitHub SCM connector that conforms to the normalized ingestion contract and supports scoped full and incremental ingestion of Markdown, plain-text, and source files with webhook and revision metadata.; Implement a SharePoint CMS connector that conforms to the normalized ingestion contract and supports scoped full and incremental ingestion of PDF, DOCX, and HTML files with webhook and revision metadata.; Implement ingestion orchestration and triggers; Normalize, govern, and publish ingested content to the shared knowledge store.; Add deployment/configuration, tests, and documentation for the ingestion agent.; Validate end-to-end ingestion and downstream content availability.
Some checks failed
ci / test (push) Failing after 8s

This commit is contained in:
2026-09-01 14:03:17 +00:00
parent 780d0d9cd6
commit 34d9dd0f1f
26 changed files with 512 additions and 3 deletions

17
tests/test_connectors.py Normal file
View File

@@ -0,0 +1,17 @@
from datetime import datetime, timezone
from kab_ingestion.github import GitHubConnector
from kab_ingestion.sharepoint import SharePointConnector
class Secrets:
def get(self, ref): return 'token'
class GH:
def list_files(self,*a): return [{'path':'docs/a.md','content':'hello','mime_type':'text/markdown','sha':'1','html_url':'u'}]
def list_changed(self,*a): return self.list_files()
class SP:
def list_files(self,*a): return [{'id':'1','name':'a.html','text':'x','mime_type':'text/html','web_url':'u','last_modified':datetime.now(timezone.utc)}]
def delta(self,*a): return self.list_files(), 'next'
def test_github_scope_and_normalization():
c=GitHubConnector(GH(),Secrets(),{'owner':'o','repo':'r','path_prefix':'docs/','credential_ref':'s'})
assert c.full('t').documents[0].document_id == 'github:1'
def test_sharepoint_normalization():
c=SharePointConnector(SP(),Secrets(),{'site_id':'s','drive_id':'d','credential_ref':'x'})
assert c.full('t').documents[0].mime_type == 'text/html'

6
tests/test_contract.py Normal file
View File

@@ -0,0 +1,6 @@
from datetime import datetime, timezone
from kab_ingestion.models import ACL, NormalizedDocument
def test_document_requires_tenant_and_acl():
d = NormalizedDocument(document_id='x', tenant_id='t', title='a', body='b', mime_type='text/plain', source_path='a', content_hash='h', updated_at=datetime.now(timezone.utc), acl=ACL(), provenance={'connector':'x','source_uri':'u','source_id':'s','retrieved_at':datetime.now(timezone.utc)})
assert d.tenant_id == 't' and not d.acl.public

9
tests/test_governance.py Normal file
View File

@@ -0,0 +1,9 @@
import pytest
from kab_ingestion.governance import GovernedPublisher
class Store:
def upsert(self,d): self.docs=d
def delete(self,*a): pass
def test_tenant_isolation():
class D: tenant_id='other'
class B: tenant_id='acme'; documents=[D()]
with pytest.raises(PermissionError): GovernedPublisher(Store(),[]).publish(B())

View File

@@ -0,0 +1,12 @@
from kab_ingestion.orchestrator import Orchestrator
class C:
def incremental(self,t,c): return type('B',(),{'next_cursor':None})()
def full(self,t): return self.incremental(t,None)
class Cur:
def load(self,*a): return None
def save(self,*a): pass
class Pub:
def publish(self,b): pass
def test_run_success():
r=Orchestrator({'x':C()},Cur(),Pub()).run('x','t')
assert r.status == 'succeeded'