This release is a pre-release and may not be stable for production use.
tiferet-kb
A Knowledge Base extension for the Tiferet framework with HDF5-backed storage via tiferet-h5.
Overview
tiferet-kb provides a Domain-Driven Design (DDD) layer for building knowledge base applications — managing documents, sections, categories, templates, and folder hierarchies. Built on the Tiferet framework and backed by HDF5 for efficient structured storage.
Installation
pip install tiferet-kb
Requirements: Python ≥ 3.10, tiferet ≥ 2.0.0b3, tiferet-h5 ≥ 0.1.0
Quick Start
from tiferet_kb.repos.category import CategoryH5Repository
from tiferet_kb.repos.document import DocumentH5Repository
from tiferet_kb.mappers import CategoryAggregate, DocumentAggregate, DocumentSectionAggregate
# Initialize repositories pointing to a single HDF5 file.
category_repo = CategoryH5Repository(h5_file='kb.h5')
doc_repo = DocumentH5Repository(h5_file='kb.h5')
# Create a category.
category = CategoryAggregate(id='meeting-notes', name='Meeting Notes', icon='📝')
category_repo.save(category)
# Create a document.
doc = DocumentAggregate(title='Sprint Retro', category_id='meeting-notes')
doc_repo.save(doc)
# Add a section.
section = DocumentSectionAggregate(
document_id=doc.id, title='What went well',
content_type='markdown', content='- Shipped on time', position=0,
)
doc_repo.save_section(section)
# Retrieve the document with sections.
result = doc_repo.get(doc.id)
print(result.title) # 'Sprint Retro'
print(result.sections[0].title) # 'What went well'
API Reference
Domain Objects
All domain objects extend tiferet.domain.DomainObject (Pydantic v2, read-only).
Category
Lightweight metadata for classifying documents.
from tiferet_kb import Category
category = Category(
id='design-docs', # slug-style identifier
name='Design Docs',
description='Architecture and design documents',
icon='📐',
color='#8B5CF6',
)
| Field | Type | Required | Description |
|---|---|---|---|
id |
str |
yes | Slug-style identifier |
name |
str |
yes | Display name |
description |
str | None |
no | Optional description |
icon |
str | None |
no | Emoji or icon identifier |
color |
str | None |
no | Hex color string |
Document
Primary content object, composed of ordered sections.
from tiferet_kb import Document
doc = Document(title='Sprint Retro') # id, status, timestamps auto-generated
| Field | Type | Required | Description |
|---|---|---|---|
id |
str |
auto | UUID (auto-generated if absent) |
title |
str |
yes | Document title |
category_id |
str | None |
no | FK to Category |
template_id |
str | None |
no | FK to Template |
folder_id |
str | None |
no | FK to Folder |
status |
str |
auto | draft, published, or archived (default: draft) |
created_at |
str |
auto | ISO 8601 timestamp |
updated_at |
str |
auto | ISO 8601 timestamp |
sections |
List[DocumentSection] |
no | Populated by service layer |
Methods: get_section(position), section_count()
DocumentSection
A content block within a document.
| Field | Type | Required | Description |
|---|---|---|---|
id |
str |
auto | UUID |
document_id |
str |
yes | Parent document UUID |
title |
str |
yes | Section heading |
content_type |
str |
yes | text, markdown, code, table, image |
content |
str |
no | Raw content (default: '') |
position |
int |
yes | Zero-based ordering |
created_at |
str |
auto | ISO 8601 timestamp |
updated_at |
str |
auto | ISO 8601 timestamp |
Domain Events
All events use the standard DomainEvent.handle() invocation pattern:
from tiferet.events import DomainEvent
from tiferet_kb.events import AddDocument
result = DomainEvent.handle(
AddDocument,
dependencies={'document_service': doc_repo},
title='My Document',
category_id='meeting-notes',
)
Category Events
| Event | Required Params | Description |
|---|---|---|
AddCategory |
id, name |
Create a new category |
GetCategory |
id |
Retrieve by ID |
ListCategories |
— | List all categories |
UpdateCategory |
id, attribute |
Update name, description, icon, or color |
RemoveCategory |
id |
Delete (idempotent) |
Document Events
| Event | Required Params | Description |
|---|---|---|
AddDocument |
title |
Create a new document (UUID auto-generated) |
GetDocument |
id |
Retrieve with sections |
ListDocuments |
— | List with optional folder_id, category_id, status filters |
UpdateDocument |
id, attribute |
Update title, status, category_id, or folder_id |
RemoveDocument |
id |
Delete with cascading section removal |
Section Events
| Event | Required Params | Description |
|---|---|---|
AddDocumentSection |
document_id, title, content_type |
Add a section (auto-appends or explicit position) |
UpdateDocumentSection |
id, attribute + document_id |
Update title, content, or content_type |
RemoveDocumentSection |
id |
Delete a section (idempotent) |
ReorderDocumentSections |
document_id, section_ids |
Reorder sections by providing ID list |
Template Events
| Event | Required Params | Description |
|---|---|---|
AddTemplate |
name |
Create a template (optionally with initial sections list) |
GetTemplate |
id |
Retrieve with sections |
ListTemplates |
— | List with optional category_id filter |
UpdateTemplate |
id, attribute |
Update name, description, or category_id |
RemoveTemplate |
id |
Delete with cascading section removal |
ApplyTemplate |
template_id, title |
Create a document from a template (stamps sections) |
Folder Events
| Event | Required Params | Description |
|---|---|---|
AddFolder |
name |
Create a folder (optionally nested via parent_id) |
GetFolder |
id |
Retrieve by ID |
ListFolderContents |
folder_id |
List child folders and documents |
MoveFolder |
id |
Move to a new parent (circular reference check) |
MoveDocument |
document_id |
Move a document to a folder (or unfile) |
RemoveFolder |
id |
Delete folder, unfile contained documents |
Repositories
Repositories implement Service interfaces and use tiferet_h5.H5Repository for HDF5 access.
CategoryH5Repository
Stores categories as node attributes on HDF5 groups at /kb/categories/<id>.
from tiferet_kb.repos.category import CategoryH5Repository
repo = CategoryH5Repository(h5_file='kb.h5')
repo.save(category) # Create or update
repo.get('meeting-notes') # Retrieve
repo.list() # List all
repo.exists('meeting-notes') # Check existence
repo.delete('meeting-notes') # Remove (idempotent)
DocumentH5Repository
Stores documents as table rows in /kb/documents/documents and sections in /kb/documents/document_sections.
from tiferet_kb.repos.document import DocumentH5Repository
repo = DocumentH5Repository(h5_file='kb.h5')
repo.save(document) # Upsert document header
repo.get('doc-id') # Retrieve with sections joined
repo.list(status='draft', category_id='notes') # Filtered listing
repo.save_section(section) # Upsert a section
repo.get_sections('doc-id') # List sections by position
repo.reorder_sections('doc-id', ['s2', 's1']) # Reorder sections
repo.delete_section('section-id') # Remove a section
repo.delete('doc-id') # Cascade delete doc + sections
HDF5 Storage Layout
/kb/
├── categories/
│ └── <category_id>/ ← group node, attrs: name, description, icon, color
├── documents/
│ ├── documents ← table: id, title, category_id, status, ...
│ └── document_sections ← table: id, document_id, title, content, position, ...
├── templates/
│ ├── templates ← table: id, name, description, category_id, ...
│ └── template_sections ← table: id, template_id, title, default_content, position, ...
└── folders/
└── <folder_id>/ ← group node, attrs: name, parent_id, path, created_at
Architecture
tiferet_kb/
├── assets/ Error code constants
├── domain/ DomainObject subclasses (Category, Document, DocumentSection)
├── interfaces/ Service ABC contracts (CategoryService, DocumentService)
├── mappers/ Aggregate + NodeObject + TableObject mappers
│ └── tests/ Harness-based tests (AggregateTestBase, NodeObjectTestBase)
├── events/ DomainEvent subclasses (CRUD operations)
└── repos/ H5Repository implementations
Development
# Create virtual environment and install with test deps
python3.10 -m venv .venv
source .venv/bin/activate
pip install -e ".[test]"
# Run tests
pytest --verbose
Documentation
Guide docs are available in docs/guides/:
License
BSD 3-Clause License. See LICENSE for details.
Metadata
Release files for tiferet-kb 1.0.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tiferet_kb-1.0.0a1.tar.gz | 73.6 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tiferet_kb-1.0.0a1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 179.8 kB
Release files / tiferet_kb-1.0.0a1.tar.gz
| Download URL | tiferet_kb-1.0.0a1.tar.gz |
|---|---|
| Size | 73.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
23fd6f29a75f547d9b7e30e230a485aa0b3b2950e55cc8fc0f57924ae2833562
|
|
BLAKE2b-256 checksum How to use checksums |
59fcd07000e2b9bca09d9c8dd3bcac6e47e1ce9fca88976b5804aa320658886f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / tiferet_kb-1.0.0a1-py3-none-any.whl
| Download URL | tiferet_kb-1.0.0a1-py3-none-any.whl |
|---|---|
| Size | 106.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
abe0c73d3bc36870dd92f836346ff76406282a49bb54dd77d412e18969b60cc9
|
|
BLAKE2b-256 checksum How to use checksums |
55bdf4aa8c2627943f4d47d28ba14e6ce7a59861a81ecbdd9dc266405ab9c485
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logSecurity for tiferet-kb 1.0.0a1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for tiferet_kb-1.0.0a1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.