Nisaba is the Ancient Text Analysis and Cross-Tradition Scholarly Research
domain of the Oshun monorepo. This specification documents what is actually
implemented under libs/nisaba/ (22 publishable @nisaba/* packages) plus the
canonical Nisaba V1 API contracts in libs/contracts/src/nisaba/index.ts and
the Prisma persistence schema in libs/nisaba/database/prisma/schema.prisma.
There is no apps/nisaba or services/nisaba directory; Nisaba ships as
libraries plus generated API contracts.
Three distinct entity layers exist and are documented separately below because they do not share field shapes:
- Canonical V1 contracts (
libs/contracts/src/nisaba/) — the schemas the generated REST API (@nisaba/api-client) is built from.@nisaba/schemas— Zod schemas used by domain logic and the Prisma-backed persistence layer.@nisaba/coretypes — the shared TypeScript vocabulary (enums and domain interfaces) consumed across the engine packages.
A new engineer should read §1 first to understand the shared type vocabulary, then §2 to see how it maps to the database, then §3 for the validation layer, then §4 and §5 for the two REST surfaces.
1. Core Type Vocabulary (@nisaba/core)#
Source: libs/nisaba/core/src/types/. These are the shared enums and interfaces
imported across the engine packages. They form the lingua franca of the domain —
when a morphology parser, a transliteration engine, and a collation algorithm
all need to refer to "Hebrew," they use the same WritingSystem.HEBREW constant
from this package rather than separate string literals.
1.1 WritingSystem enum#
Defined in core/src/types/writing-systems.ts. Values are ISO 15924 (and
ISO-15924-derived) script codes, grouped below by geographic/cultural family.
Using ISO 15924 codes as enum values means they round-trip through external
standards (font selection, Unicode metadata, OpenType script tags) without a
translation step.
| Group | Members (enum key = code) |
|---|---|
| Cuneiform | SUMERIAN_CUNEIFORM='Xsux', AKKADIAN_CUNEIFORM='Xsux_Akk', ELAMITE_CUNEIFORM='Xsux_Elx', HITTITE_CUNEIFORM='Xsux_Hit', UGARITIC='Ugar', OLD_PERSIAN_CUNEIFORM='Xpeo' |
| Egyptian | EGYPTIAN_HIEROGLYPHIC='Egyp', HIERATIC='Egyp_Hier', DEMOTIC='Egyd', COPTIC='Copt' |
| Semitic | HEBREW='Hebr', PALEO_HEBREW='Hebr_Pleo', ARAMAIC='Armi', SYRIAC='Syrc', ARABIC='Arab', SOUTH_ARABIAN='Sarb', PHOENICIAN='Phnx', MOABITE='Phnx_Moab', NABATAEAN='Nbat', SAMARITAN='Samr', MANDAIC='Mand', ETHIOPIC='Ethi' |
| Greek/Latin | GREEK='Grek', LINEAR_A='Lina', LINEAR_B='Linb', CYPRIOT='Cprt', LATIN='Latn' |
| Indic | BRAHMI='Brah', GRANTHA='Gran', KHAROSHTHI='Khar', DEVANAGARI='Deva', BENGALI='Beng', TAMIL='Taml', TELUGU='Telu', KANNADA='Knda', MALAYALAM='Mlym', SINHALA='Sinh', TIBETAN='Tibt', THAI='Thai', KHMER='Khmr', BURMESE='Mymr' |
| Iranian | AVESTAN='Avst', PAHLAVI='Phli', SOGDIAN='Sogd' |
| East Asian | CHINESE='Hani', JAPANESE_KANJI='Hani_Jpan', KOREAN_HANJA='Hani_Kore' |
| Slavic | GLAGOLITIC='Glag', OLD_CYRILLIC='Cyrs' |
| Other | ARMENIAN='Armn', GEORGIAN='Geor', OLD_TURKIC='Orkh', RUNIC='Runr' |
ScriptDirection encodes the physical direction text flows on the page:
'ltr' | 'rtl' | 'ttb' | 'boustrophedon'.
WritingSystemMetadata (interface) carries the full profile needed to render
and process a script: code (WritingSystem), name, direction
(ScriptDirection), iso15924, iso639_3? (string[]), unicodeBlocks
(readonly string[]), hasCombiningCharacters (boolean), hasLigatures
(boolean).
1.2 Tradition enum#
Defined in core/src/types/traditions.ts. The Tradition enum names the
religious and philosophical traditions whose texts Nisaba manages. It is used as
a first-level grouping key in canonical references, corpus connectors, and the
comparative analysis package.
- Abrahamic:
CHRISTIANITY,JUDAISM,ISLAM,BAHAI,SAMARITANISM,MANDAEISM - Dharmic:
HINDUISM,BUDDHISM,JAINISM,SIKHISM - East Asian:
CONFUCIANISM,TAOISM,SHINTO - Iranian:
ZOROASTRIANISM,MANICHAEISM - Ancient Near Eastern:
SUMERIAN,BABYLONIAN,EGYPTIAN,CANAANITE,HITTITE,UGARITIC - Classical:
GREEK_PHILOSOPHY,ROMAN,NEOPLATONISM,STOICISM,GNOSTICISM,HERMETICISM - Other:
INDIGENOUS,NEW_RELIGIOUS_MOVEMENT,SECULAR_PHILOSOPHY,CROSS_TRADITION
TraditionMetadata (interface) carries the displayable and computable profile
of each tradition: tradition, displayName, primaryLanguages,
primaryScripts, approximateDateRange
({ earliest: number; latest: number | null }), geographicOrigin,
parentTraditions (readonly Tradition[]).
1.3 Morphology types#
Defined in core/src/types/morphology.ts. These enums and the
MorphologicalParse interface form the universal output format for all of
Nisaba's language-specific morphological analyzers — so that downstream
consumers (the UI, the study plan engine, the annotation system) never need to
handle language-specific morphology formats.
The grammatical feature enums:
PartOfSpeech—noun, verb, adjective, adverb, pronoun, preposition, conjunction, particle, interjection, article, numeral, determiner, auxiliary, postposition, classifier, ideogram, unknownGrammaticalGender—masculine, feminine, neuter, common, animate, inanimateGrammaticalNumber—singular, dual, trial, plural, collectiveGrammaticalPerson—first, second, thirdGrammaticalCase—nominative, accusative, genitive, dative, ablative, vocative, locative, instrumental, ergative, absolutive, construct, obliqueVerbTenseAspect—present, past, future, aorist, perfect, pluperfect, imperfect, future_perfect, preterite, stative, durative, punctualVerbMood—indicative, subjunctive, optative, imperative, jussive, cohortative, precative, prohibitive, infinitive, participleVerbVoice—active, passive, middle, medio-passive, causative, reflexiveVerbStem— Hebrew (qal, niphal, piel, pual, hiphil, hophal, hithpael), Akkadian (G, D, S, N, Gt, Dt, St, Nt), Arabic (form_I…form_X)
MorphologicalParse (interface) is the result type returned by every
morphological analyzer. It carries: surfaceForm (the original text token),
lemma (the dictionary form), language (ISO 639-3 code), pos (part of
speech); optional nominal features (gender, number, case, state),
optional verbal features (person, tenseAspect, mood, voice, stem),
optional root, affixes (prefix, suffix, proclitic, enclitic),
confidence (0–1 score), and alternateParses? for ambiguous forms.
1.4 Lexicon types#
Defined in core/src/types/lexicon.ts. These types describe structured lexical
entries returned by the unified LexiconService. The LexiconEntry shape is
language-neutral so the same downstream display code works for Hebrew, Greek,
Sanskrit, and Akkadian entries.
Key types: LexicalSense, LexicalExample, LexicalCrossRef (relationType:
synonym | antonym | cognate | derived | related | see_also), and
LexiconEntry carrying: id, lemma, language, writingSystem, optional
transliteration/pronunciation, partOfSpeech, root?, pattern?,
gender?, senses, etymology?, cognates?, crossRefs?,
frequency/attestation fields, and external lexicon IDs (strongsNumber,
bdbEntry, halalEntry, lsjEntry), plus sources and lastUpdated.
1.5 Reference types#
Defined in core/src/types/reference.ts. These types describe the canonical
reference system used by @nisaba/canon to give every passage in every
tradition a stable, dereferenceable identifier.
ReferenceSystemTypeenumerates the citation schemes in use across traditions. Values:chapter_verse, stephanus, bekker, diels_kranz, pitaka_nikaya, adhyaya_shloka, sutra_verse, page_line, folio_line, tablet_line, column_line, section_paragraph, customCanonicalReferenceSystem(interface) describes a single reference system:id,name,tradition,type,canon?,uriPrefix,referencePattern?,supportsRanges,notes?CanonicalRef(interface) is a parsed reference to a specific passage:raw(the original string),tradition,canon,book,system, optional structural components (chapter,verse,verseEnd,section,page,line,lineEnd,fragment), and the computeduriCanonicalRefRangegroups a start and endCanonicalRefwith a human-readabledisplayString
1.6 Transliteration types#
Defined in core/src/types/transliteration.ts. The TransliterationScheme enum
names every romanization and transcription scheme that Nisaba supports, grouped
by language family. Using a typed enum prevents the subtle bugs that arise from
inconsistent scheme naming (e.g., "IAST" vs. "iast" vs. "iso-233").
TransliterationScheme values by family:
- Hebrew:
SBL_HEBREW,ACADEMIC_HEBREW,SIMPLIFIED_HEBREW - Arabic:
DIN_31635,BUCKWALTER,ALA_LC_ARABIC - Greek:
SBL_GREEK,BETA_CODE,SIMPLIFIED_GREEK - Akkadian/Sumerian:
ATF,CDLI - Sanskrit/Pali:
IAST,ITRANS,SLP1,HARVARD_KYOTO,VELTHUIS,ISO_15919 - Syriac:
SYRIAC_ROMANIZATION - Egyptian:
MANUEL_DE_CODAGE,JSesh - Tibetan:
WYLIE,EXTENDED_WYLIE - Coptic:
COPTIC_ROMANIZATION - General:
IPA,ASCII,UNICODE
TransliterationConfig (interface) specifies the parameters for a
transliteration operation: scheme, preserveDiacritics,
preserveWordBoundaries, includeVowels, normalizeWhitespace (all boolean).
1.7 Manuscript, apparatus, and annotation core types#
These types in @nisaba/core describe the physical and scholarly properties of
manuscripts and the data structures used in textual criticism. They are used by
both the @nisaba/criticism engine and the persistence layer.
core/src/types/manuscript.ts defines:
ManuscriptMaterialType— the physical medium of a manuscript. Values:PAPYRUS, PARCHMENT, VELLUM, CLAY_TABLET, PAPER, STONE, METAL, WOOD, BAMBOO, PALM_LEAF, SILK, BONE, CERAMIC, WAX_TABLET, OTHERVariantClassificationType— the scholarly classification of a textual variant. All 22 values:ORTHOGRAPHIC, PHONETIC, MORPHOLOGICAL, LEXICAL, SYNTACTIC, TRANSPOSITION, ADDITION, OMISSION, SUBSTITUTION, CONFLATION, HARMONIZATION, HOMOEOTELEUTON, HOMOEOARCTON, DITTOGRAPHY, HAPLOGRAPHY, METATHESIS, CORRECTION, MARGINAL_NOTE, GLOSS, INTERPOLATION, LACUNA, OTHER
core/src/types/apparatus.ts defines the data structures for critical apparatus
entries — the footnotes in a critical edition that document textual variants:
ApparatusFormatType/ApparatusFormat— the apparatus presentation style. Values:POSITIVE, NEGATIVE, FULL, SELECTIVE, LEIDEN_PLUSVariantClassification— same 22 values asVariantClassificationTypeApparatusReading(interface) — one manuscript witness's reading of a variant unit:text,witnesses(readonly string[]),isPreferred,classification?,note?ApparatusEntry(interface) — a complete variant unit entry with itsreference,lemma, allreadings(readonly ApparatusReading[]), andsignificancescore (0–10)
core/src/types/annotations.ts defines the W3C-aligned annotation type system:
AnnotationTypeValue— the semantic role of an annotation. Values:COMMENT, HIGHLIGHT, BOOKMARK, TAG, CLASSIFICATION, LINKING, DESCRIBING, IDENTIFYING, MODERATING, QUESTIONING, REPLYING, TRANSLATION, TRANSCRIPTIONAnnotationMotivation— the W3C Web Annotation vocabulary for why an annotation exists:assessing, bookmarking, classifying, commenting, describing, editing, highlighting, identifying, linking, moderating, questioning, replying, tagging- W3C selector types for targeting text:
TextQuoteSelector,TextPositionSelector,FragmentSelector,XPathSelector; union typeAnnotationSelector
1.8 Comparative types#
Defined in core/src/types/comparative.ts. These types support the scholarly
rigor of the cross-tradition comparison system — preventing superficial
syncretism by requiring every claim about similarity or influence to declare its
type, evidence grade, and level of scholarly consensus.
SimilarityTaxonomy— the kind of relationship being claimed between concepts across traditions. Values:THEMATIC, LEXICAL, STRUCTURAL, GENEALOGICAL, TYPOLOGICAL, MORPHOLOGICAL, PHONETIC, SEMANTIC, SYNTACTIC, NARRATIVE, DOCTRINAL, RITUAL, ICONOGRAPHICEvidenceGradeType— how strongly the evidence supports a claim. Values:CERTAIN, HIGHLY_PROBABLE, PROBABLE, POSSIBLE, UNCERTAIN, SPECULATIVE, DISPUTEDConsensusLevelType— how widely the scholarly community agrees with a claim. Values:UNIVERSAL, STRONG, MAJORITY, DIVIDED, MINORITY, INDIVIDUAL, UNKNOWNComparativeEvidence(interface) — a single piece of evidence supporting a comparative claim:type(textual | archaeological | linguistic | historical | iconographic | structural),source,reference,description,grade,date?InfluenceDirection— the direction of a textual influence relationship:forward, reverse, bidirectional, uncertain
2. Persistence Schema (@nisaba/database)#
Source: libs/nisaba/database/prisma/schema.prisma. Nisaba uses PostgreSQL via
Prisma. The datasource URL is env("NISABA_DATABASE_URL"). Preview features
fullTextSearch and fullTextIndex are enabled to support the cross-corpus
lemma-aware search.
The generated Prisma client is not imported directly by consumers — instead it
is re-exported through the three lifecycle functions in
database/src/client.ts: getNisabaClient(), createNisabaClient(), and
disconnectNisabaClient(). This pattern allows connection pooling and teardown
to be managed centrally.
2.1 Database enums#
The Prisma schema defines its own database-level enums (separate from the
TypeScript enums in @nisaba/core) because the persistence layer uses
string-serialized enum values. The major enums and their value counts:
ManuscriptMaterial (15 values), ManuscriptScriptType (16 values:
UNCIAL, MINUSCULE, MAJUSCULE, CURSIVE, SEMI_CURSIVE, HIERATIC, DEMOTIC, CUNEIFORM_WEDGE, SQUARE_HEBREW, PROTO_HEBREW, KUFIC, NASKH, NASTALIQ, BRAHMI, DEVANAGARI, OTHER),
VariantClassification (22 values), VariantCause (10 values:
SCRIBAL_ERROR, DELIBERATE_CHANGE, THEOLOGICAL_MOTIVATION, HARMONIZATION, LITURGICAL_ADAPTATION, STYLISTIC_IMPROVEMENT, CLARIFICATION, CENSORSHIP, DAMAGE, UNCERTAIN),
ApparatusFormat (5 values), AnnotationType (13 values), AnnotationStatus
(6 values: ACTIVE, ARCHIVED, DELETED, UNDER_REVIEW, APPROVED, REJECTED),
SimilarityType (13 values), EvidenceGrade (7 values), ConsensusLevel (7
values), ProjectStatus (6 values:
PLANNING, ACTIVE, ON_HOLD, COMPLETED, ARCHIVED, CANCELLED), ProjectType (9
values:
TEXT_EDITION, COLLATION, TRANSLATION, COMMENTARY, COMPARATIVE_STUDY, PALEOGRAPHIC_ANALYSIS, CORPUS_BUILDING, LEXICOGRAPHY, OTHER),
EditionStatus (7 values:
DRAFT, IN_PROGRESS, REVIEW, PUBLISHED, REVISED, SUPERSEDED, WITHDRAWN).
2.2 Models (tables)#
The 16 Prisma models map to PostgreSQL tables. The table below summarizes the
purpose and key fields of each model. All models carry createdAt/updatedAt
timestamps; most carry an ownerId (VarChar 50) that is indexed for per-user
queries.
| Model | Table | Key fields |
|---|---|---|
Manuscript |
manuscripts |
id (cuid, VarChar 25), siglum, name, physical description, provenance, dating, scholarly assessment, digital images, ownerId |
CollationProject |
collation_projects |
id, name, witnesses (String[]), config (Json), status, progress, totalVariantUnits, significantVariants |
VariantUnit |
variant_units |
id, collationProjectId, reference, startOffset/endOffset, baseReading, lemma?, readings (Json), classification?, cause?, significance |
CriticalEdition |
critical_editions |
id, title, version, collationProjectId?, text, apparatus (Json), apparatusFormat, status, editor?, editors (Json) |
Annotation |
annotations |
id, targetUri, targetType, targetSelector? (Json), type, body, bodyFormat, motivation?, status, layerId?, manuscriptId?, tags |
AnnotationLayer |
annotation_layers |
id, name, description?, color?, scope?, permissions (Json), ownerId |
ConceptMapping |
concept_mappings |
id, source concept (tradition/concept/language/reference), target concept, similarityType, similarityScore, evidenceGrade, consensusLevel, evidence (Json) |
MotifAttestation |
motif_attestations |
id, motifId, motifName, motifCategory?, tradition, textReference, passage?, function?, evidenceGrade |
InfluenceEdge |
influence_edges |
id, source (sourceId/sourceType/sourceTradition), target, influenceType, direction, strength, evidenceGrade, consensusLevel, temporal context |
CanonicalReference |
canonical_references |
id, tradition, canon, collection?, bookId, bookName, chapterCount?, verseCount?, structure? (Json), canonicalOrder, versificationScheme?/versificationMap? |
Passage |
passages |
id (uuid), slug (unique), title, summary, primaryDomain, domains (String[]), origin, status, visibility, reference/language/text/provenance (Json), wordCount, translations/parallelPassages/commentary/annotations (Json) |
PaleographicAnalysis |
paleographic_analyses |
id, manuscriptId, scriptClassification?, dateEstimate?/dateEarliest?/dateLatest?/dateConfidence?, region?, features/letterForms/abbreviations/ligatures (Json), handCount |
ScribalHand |
scribal_hands |
id, manuscriptId, analysisId?, handLabel, folioRange?/startFolio?/endFolio?, scriptStyle?, characteristics/letterForms (Json), scribeName? |
ResearchProject |
research_projects |
id, name, type (ProjectType), status (ProjectStatus), config/members/milestones (Json), traditions/languages (String[]), progress, ownerId, organizationId? |
PersonalLibraryItem |
personal_library_items |
id, itemType, itemId, itemTitle, collection?, tags, readingStatus?/readingProgress?, notes?, highlights (Json), citation? |
Bookmark |
bookmarks |
id, targetUri, targetTitle, targetType, position? (Json), label?/notes?/color?, folder?, tags, sortOrder |
2.3 Persistence invariants#
The schema enforces data quality through unique constraints, cascade rules, and soft-delete patterns. The key invariants:
Manuscript:@@unique([ownerId, siglum])— no two manuscripts belonging to the same owner may share a siglum. Relations:variantUnits,paleographicAnalyses,scribalHands,annotations. Soft delete viadeletedAt.VariantUnit→CollationProject(onDelete: Cascade); optionalmanuscriptrelation.CriticalEdition→ optionalCollationProjectrelation.Annotation→ optionalAnnotationLayerandManuscriptrelations; soft delete viadeletedAt.AnnotationLayer:@@unique([ownerId, name]).ConceptMapping:@@unique([ownerId, sourceTradition, sourceConcept, targetTradition, targetConcept])— prevents duplicate concept equivalence claims by the same scholar.InfluenceEdge:@@unique([sourceId, targetId, influenceType, ownerId]).CanonicalReference:@@unique([tradition, canon, bookId])— each book in a canon has exactly one canonical reference record.PaleographicAnalysis→Manuscript(onDelete: Cascade); hasscribalHands.ScribalHand→Manuscript(onDelete: Cascade); optionalanalysisrelation.PersonalLibraryItem:@@unique([ownerId, itemType, itemId]).
The generated Prisma client exposes delegates for: manuscript,
collationProject, variantUnit, criticalEdition, annotation,
annotationLayer, conceptMapping, motifAttestation, influenceEdge,
canonicalReference, passage, paleographicAnalysis, scribalHand,
researchProject, personalLibraryItem, bookmark.
3. Validation Schemas (@nisaba/schemas)#
Source: libs/nisaba/schemas/src/. These are Zod schemas (and inferred types)
for the domain entities that cross trust boundaries — API request bodies, corpus
ingestion payloads, and data from external scholarly platforms. The schemas
serve as both a runtime firewall against invalid input and a source of
TypeScript types, so the same Zod definition drives both validation and the type
system.
Each schema module exports a Create* variant (.omit({ id: true })) and most
export an Update* variant (.partial().omit({ id: true, ownerId: true })).
The full field-level details of each module follow.
3.1 manuscript.ts#
Schemas for manuscript records and queries. The ManuscriptSchema captures both
the physical description of the artifact and its scholarly metadata.
- Enum schemas:
ManuscriptMaterialSchema,ManuscriptScriptTypeSchema,EvidenceGradeSchema. ManuscriptDimensionsSchema—{ height, width (positive), unit ('mm' | 'cm' | 'in') }, strict.WitnessClassificationSchema—textualFamily?,textType?,reliability?(0–1),completeness?(0–1),notes?.ManuscriptSchema—id?,siglum,name,alternateNames,catalogNumber?,material?,scriptType?,dimensions?,folioCount?,columnCount?,linesPerColumn?,contents?,languages,writingSystem?, provenance fields, dating fields, scholarly assessment,digitalImages({ url, label?, type? }[]),iiifManifestUrl?(URL),transcriptionUrl?,externalIds,bibliography,notes?,metadata,ownerId,projectId?.ManuscriptQuerySchema— filter fields pluslimit(1–100, default 20),offset,orderBy(siglum | name | dateEarliest | dateLatest | createdAt),orderDir(asc | desc).
3.2 variant.ts#
Schemas for collation projects and textual variants — the input and output of the collation engine.
VariantClassificationSchema(22 values),VariantCauseSchema(10 values),ProjectStatusSchema(6 values).VariantReadingSchema—text,witnesses(string[]),isPreferred,classification?,cause?,note?.VariantUnitSchema—id?,collationProjectId,reference,startOffset/endOffset(int ≥ 0),baseReading,lemma?,readings,classification?,cause?,significance(0–10),preferredReading?,rationale?,evidenceGrade?,manuscriptId?,notes?,metadata. Refinement:endOffset >= startOffset.CollationConfigSchema—algorithm(needleman-wunsch | smith-waterman | gotoh | medite | collatex),matchScore,mismatchPenalty,gapPenalty,normalizeUnicode,caseSensitive,ignoreAccents,ignorePunctuation,tokenizer(word | character | morpheme).CollationResultSchema—projectId,totalVariantUnits,significantVariants,agreementPercentage(0–100),witnesses,executionTimeMs?.CollationProjectSchema—id?,name,description?,baseText?,witnesses,collationMethod?,config?,status(ProjectStatus, defaultPLANNING),ownerId.
3.3 apparatus.ts#
Schemas for critical apparatus entries and edition configuration. The
ApparatusConfigSchema controls how apparatus entries are presented, while
CriticalEditionSchema describes a complete critical edition record.
ApparatusFormatSchema(5 values),EditionStatusSchema(7 values).ApparatusReadingSchema—text,witnesses,isPreferred,classification?,note?.ApparatusEntrySchema—reference,lemma,readings(min 1),significance(0–10),note?.ApparatusConfigSchema—format(defaultPOSITIVE),includeOrthographic,minimumSignificance(0–10),showWitnessDescriptions,groupByFamily,language.CriticalEditionSchema—id?,title,description?,version,collationProjectId?,text,apparatus,apparatusFormat,status(EditionStatus, defaultDRAFT),editor?,editors({ name, role? }[]),methodology?,bibliography,metadata,ownerId.
3.4 annotation.ts#
Schemas for standoff annotations and annotation layers, aligned with the W3C Web
Annotation Data Model. The selector schemas enforce the W3C geometry constraints
(e.g., end >= start for position selectors).
AnnotationTypeSchema(13 values),AnnotationStatusSchema(6 values),AnnotationMotivationSchema(13 W3C values).- W3C selector schemas:
TextQuoteSelectorSchema,TextPositionSelectorSchema(refinement:end >= start),FragmentSelectorSchema,XPathSelectorSchema; discriminated unionAnnotationSelectorSchema. AnnotationSchema—id?,targetUri,targetType,targetSelector?,type,body,bodyFormat(defaulttext/plain),language?,motivation?,status(defaultACTIVE),layerId?,manuscriptId?,tags,metadata,ownerId,projectId?.AnnotationLayerSchema—id?,name,description?,color?,scope?,permissions,metadata,ownerId.AnnotationExportSchema—format(w3c | json | csv | tei, defaultw3c),layerIds?,types?,includeDeleted.
3.5 reference.ts#
Schemas for canonical reference records and queries. These ensure that reference data entering the system is structurally valid — for example, that a versification mapping has consistent source and target scheme identifiers.
ReferenceSystemTypeSchema(13 values).CanonicalReferenceSchema—id?,tradition,canon,collection?,bookId,bookName,bookAbbreviation?,alternateNames,chapterCount?,verseCount?,structure?,canonicalOrder,originalLanguage?,languages,versificationScheme?,versificationMap?,externalIds,metadata.VersificationMappingSchema—sourceScheme,targetScheme,bookId,mappings({ sourceChapter, sourceVerse, targetChapter, targetVerse, note? }[]).ReferenceRangeSchema—startTradition/startCanon/startBookplus optional chapter/verse, optional end fields.ReferenceQuerySchema—tradition?,canon?,bookId?,search?,limit(1–500, default 50),offset.
3.6 tradition.ts#
Schemas for cross-tradition comparative data — concept mappings, motif attestations, and influence edges. The evidence grading and consensus level fields are enforced at the schema level, requiring every comparative claim to declare its epistemic status.
SimilarityTypeSchema(13 values),ConsensusLevelSchema(7 values).ConceptMappingSchema— source/target concept fields,similarityType,similarityScore(0–1),evidenceGrade(defaultPOSSIBLE),consensusLevel(defaultUNKNOWN),evidence(typed array),bibliography,notes?,metadata,ownerId.MotifSchema—id?,motifId,motifName,motifCategory?,tradition,textReference,passage?,language?,function?,context?,dating?,evidenceGrade(defaultPROBABLE),bibliography,metadata,ownerId.InfluenceEdgeSchema—id?,sourceId/sourceType/sourceTradition,targetId/targetType/targetTradition,influenceType,direction(forward | reverse | bidirectional | uncertain, defaultforward),strength(0–1),evidenceGrade,consensusLevel,dateEarliest?,dateLatest?,period?,evidence,bibliography,notes?,metadata,ownerId.
3.7 corpus.ts#
Schemas for corpus metadata and paleographic analysis records. The
DateEstimationSchema is notable because it requires the dating method to be
declared explicitly — distinguishing paleographic estimates from radiocarbon
dates from colophon evidence — which matters for downstream confidence
calculation.
CorpusMetadataSchema—id?,name,description?,tradition?,language,writingSystem?,dateRange?({ earliest, latest }),textCount,tokenCount,genre?,source?,license?,version,format(plain | tei | conll | json | xml),encoding(defaultutf-8),metadata,ownerId.PaleographicFeatureSchema—featureName,featureCategory(letter_form, stroke_pattern, ductus, angle, proportion, spacing, decoration, ligature, abbreviation, ruling, other),value,description?,confidence(0–1),reference?.DateEstimationSchema—dateEarliest/dateLatest,confidence(EvidenceGrade),method(paleographic, radiocarbon, archaeological, historical, stylistic, colophon, other),comparanda,rationale?. Refinement:dateLatest >= dateEarliest.ScribalHandSchema—id?,manuscriptId,analysisId?,handLabel,handDescription?, folio range fields,scriptStyle?,characteristics,letterForms,dateEstimate?,dateConfidence?,scribeName?,scribeIdentification?,notes?,metadata.PaleographicAnalysisSchema—id?,manuscriptId,scriptClassification?, dating fields,region?,features,letterForms,abbreviations,ligatures,handCount,rulingPattern?,inkDescription?,decorations,methodology?,comparanda,bibliography,notes?,metadata,ownerId.
3.8 geotemporal.ts#
Schemas for geographic and temporal data about manuscripts and traditions. The
FuzzyDateSchema is the domain's standard representation for ancient dates
where the exact year is unknown — using earliest/latest integer bounds and a 0–1
confidence score rather than a single uncertain date.
FuzzyDateSchema—earliest/latest(int),confidence(0–1),label?,calendar(gregorian, julian, hebrew, islamic, buddhist, other, defaultgregorian). Refinement:latest >= earliest.ProvenanceEventSchema—date?(FuzzyDate),location?,event(created, copied, acquired, sold, donated, stolen, discovered, restored, transferred, other),description?,actor?,source?,confidence(EvidenceGrade, defaultPROBABLE).ProvenanceChainSchema—manuscriptId,events,notes?,bibliography,metadata.HistoricalLocationSchema—id?,name,modernName?,alternateNames,latitude?(−90…90),longitude?(−180…180),region?,country?,dateRange?,description?,type?(city, temple, monastery, scriptorium, library, archaeological_site, region, province, kingdom, other),tradition?,externalIds,metadata.TimelineEventSchema—id?,title,description?,date(FuzzyDate),location?,tradition?,category?(composition, translation, discovery, publication, council, schism, persecution, founding, destruction, reform, contact, other),significance(0–10),relatedTexts,relatedPersons,bibliography,metadata.GeospatialQuerySchema—latitude/longitude,radiusKm(positive, default 50),dateRange?,tradition?,type?,limit(1–100, default 20).
4. Canonical V1 API (@nisaba/api-client + libs/contracts/src/nisaba)#
The V1 REST API is the stable public surface through which other Oshun services and external consumers interact with Nisaba data. It is generated from Zod contracts rather than hand-written, which means the OpenAPI document, the TypeScript types, and the validation logic are all derived from a single source of truth.
The generation chain is: Zod contracts in libs/contracts/src/nisaba/index.ts →
OpenAPI 3.1 document at libs/openapi/src/specs/nisaba/nisaba-v1-contracts.yaml
→ generated typed client at libs/nisaba/api-client/src/client.ts
(createNisabaApiClient). The OpenAPI types live in
api-client/src/generated/openapi.ts. All generation is driven by
libs/openapi/scripts/generate-oshun-v1-api-clients.ts.
4.1 Endpoints#
The base path is /api/v1/nisaba. All endpoints require Bearer JWT
authentication (bearerAuth). Every resource exposes the same five-operation
surface:
| Method | Path | Operation (resource = <R>) |
Purpose |
|---|---|---|---|
| GET | /api/v1/nisaba/<R> |
listNisaba<R> |
Paginated list (cursor) |
| POST | /api/v1/nisaba/<R> |
createNisaba<R> |
Create record |
| GET | /api/v1/nisaba/<R>/{sourceRecordId} |
getNisaba<R> |
Fetch one record |
| PUT | /api/v1/nisaba/<R>/{sourceRecordId} |
upsertNisaba<R> |
Upsert by source record id |
| DELETE | /api/v1/nisaba/<R>/{sourceRecordId} |
tombstoneNisaba<R> |
Soft-delete (tombstone) |
The 13 resources covered by this surface: passages, manuscripts, editions,
translations, lexicon-entries, morphology-entries, annotations,
concept-graph-nodes, concept-graph-edges, notebooks, study-plans,
citations, scholar-profiles.
List operations accept LimitParam, CursorParam, and
IncludeTombstonesParam. Standard error responses: 400 BadRequest, 401
Unauthorized, 403 Forbidden, 409 Conflict, 500 InternalError. Tombstone
responses use TombstoneResponse.
4.2 V1 contract entities#
Source: libs/contracts/src/nisaba/index.ts. All entities use UUID id and ISO
timestamps (createdAt/updatedAt). The entity shapes here are the V1 public
contract — they differ from the @nisaba/schemas shapes in §3 because the
public API surface is designed for interoperability, not internal domain
richness.
Shared value objects and enums#
These small types are used across multiple V1 entities:
NisabaScript—latin, greek, hebrew, arabic, devanagari, pali-sinhala, coptic, cuneiform, tibetan, chinese, japanese, syriac, ethiopic, otherTextDirection—ltr, rtl, vertical, boustrophedonTextFormat—plain-text, markdown, tei-xml, htmlPassageStatus—draft, review, published, archivedReviewState—unreviewed, in-review, approved, rejectedPartOfSpeech—noun, verb, adjective, adverb, pronoun, particle, preposition, conjunction, interjection, numeral, proper-noun, unknownMorphologyFeature—case, number, gender, person, tense, aspect, mood, voice, state, degree, stem, root, prefix, suffixCitationStyle—chicago, mla, apa, sbl, cts, customRightsStatus—public-domain, open-license, licensed, restricted, unknownScholarCredentialKind—academic-degree, faculty-appointment, editorial-role, translator-credit, institutional-affiliation, community-expertCanonicalReference—scheme(cts | osis | sefaria | library-of-congress | custom),reference,normalizedReference,urn(nullable),workId(slug),workTitle,divisionPath(≤ 12 entries)TextRangeSelector—segmentId(nullable UUID),startOffset,endOffset,quote(nullable). Refinement:endOffset > startOffset
Passage#
A Passage is the fundamental text unit in the V1 API — a contiguous piece of
text with a canonical reference, broken into PassageSegment records that
enable fine-grained annotation and morphology tagging.
Fields: id, canonicalReference, title, tradition, language, script,
direction, text, normalizedText, textFormat, segments (1–2000
PassageSegment records), sourceLineage (manuscriptIds, editionId
nullable, translationIds, citationIds), conceptNodeIds, lexiconEntryIds,
morphologyEntryIds, annotationIds, status, timestamps. PassageSegment —
segmentId, label, order, text, startOffset, endOffset.
Manuscript#
A Manuscript is a physical or digital artifact witness to a text tradition, with full digitization and rights metadata.
Fields: id, siglum, title, tradition, language, script, repository
(name, city, country, shelfmark, catalogUrl), dateRange
(notBefore, notAfter, displayLabel), material
(papyrus | parchment | paper | stone | clay | metal | digital), extent
(folioCount, lineCount, completeness:
complete | fragmentary | excerpt | unknown), digitization (status:
not-digitized | digitized | iiif | transcribed, imageManifestUrl,
transcriptionId, ocrQualityBand: human | high | mixed | low | none),
rights (status, licenseLabel, attribution), relatedPassageIds,
timestamps.
Edition#
An Edition groups manuscripts under a scholarly editor's apparatus and publication record.
Fields: id, workId, title, editionType
(critical | diplomatic | reader | digital | facsimile), language, script,
manuscriptIds (1–300), editorScholarProfileIds (1–40), apparatus (≤ 1000
ApparatusEntry), publication (status, publisher, publicationDate,
doi, isbn), review (state, reviewerScholarProfileId, reviewedAt),
timestamps. ApparatusEntry — entryId, passageSegmentId, lemma,
reading, witnessManuscriptIds (1–100), note.
Translation#
A Translation links a source-language passage to a target-language rendering with provenance and rights metadata.
Fields: id, passageId, editionId (nullable), sourceLanguage,
targetLanguage, locale, translatorScholarProfileIds (1–20), title,
text, textFormat, translationMode
(literal | formal-equivalence | dynamic | commentarial | adaptive), rights,
review, timestamps.
LexiconEntry#
A LexiconEntry is a structured dictionary entry for one lemma, with full sense decomposition, etymology, and inflection data.
Fields: id, lemma, normalizedLemma, language, script,
transliteration (nullable), partOfSpeech, roots, glosses (1–50),
senses (1–100 LexiconSense: senseId, order, gloss, semanticDomain,
passageIds), etymology (nullable), inflectedForms, sourceCitationIds
(1–100), relatedEntryIds, reviewState, timestamps.
MorphologyEntry#
A MorphologyEntry records the morphological parse of a single token within a passage segment, with provenance indicating whether the parse was human-reviewed or machine-generated.
Fields: id, passageId, segmentId, tokenIndex, surface,
normalizedSurface, lemmaEntryId (nullable), partOfSpeech, features
({ feature, value }[]), parsing (method:
human | rule-engine | model-assisted | imported, score,
reviewerScholarProfileId, reviewedAt), sourceCitationIds (1–20),
timestamps.
Annotation#
An Annotation is a scholarly note, highlight, variant reading, or commentary targeted at a passage, segment, manuscript, or edition.
Fields: id, target (kind:
passage | segment | translation | manuscript | edition | token, objectId,
selector nullable), kind
(highlight | note | question | variant-note | commentary | cross-reference | morphology | lexicon),
body (nullable), authorUserId, visibility (private | shared | public),
tags, linkedNotebookIds, citationIds, status
(active | resolved | archived), timestamps.
ConceptGraphNode#
A ConceptGraphNode represents a concept, deity, place, person, or thematic unit in the cross-tradition knowledge graph.
Fields: id, slug, label, kind
(term | deity | place | person | textual-theme | ritual-practice | cosmology | historical-event | school | manuscript-family),
summary, traditions (1–40), languageCoverage (1–40), aliases,
passageIds, lexiconEntryIds, externalRefs
({ authority, identifier, url }[]), reviewState, timestamps.
ConceptGraphEdge#
A ConceptGraphEdge connects two concept graph nodes with a typed, evidenced
relationship. High-confidence edges must cite supporting passages or citations —
this is enforced by the superRefine invariant in §4.3.
Fields: id, sourceNodeId, targetNodeId, relation
(broader-than | narrower-than | related-to | influences | contrasts-with | translation-equivalent | ritualizes | comments-on | shares-source-lineage),
direction (directed | undirected), evidencePassageIds, citationIds,
confidenceBand (high | medium | low | contested), rationale, timestamps.
Notebook#
A Notebook is a scholar's personal or collaborative research workspace, collecting passages, annotations, and concepts with optional collaborators.
Fields: id, ownerUserId, title, summary (nullable), kind
(research | translation | philology | teaching | reflection | collection),
visibility, passageIds, annotationIds, conceptNodeIds, citationIds,
collaborators ({ userId, role: owner|editor|commenter|viewer, addedAt }[]),
items (NotebookItem: itemId, kind, targetId, title, body,
order), tags, timestamps.
StudyPlan#
A StudyPlan is a structured learning path through Nisaba's texts, with typed steps that map to specific scholarly activities.
Fields: id, userId, title, objective, level
(introductory | intermediate | advanced | scholar), status
(draft | active | paused | completed | archived), notebookId (nullable),
passageIds, conceptNodeIds, steps (1–300 StudyPlanStep: stepId,
order, kind, targetId, title, dueAt, completedAt), startedAt,
completedAt, timestamps. StudyPlanStep.kind values:
read-passage, compare-translation, view-manuscript, lexicon-review, morphology-review, concept-map, annotation, reflection, assessment.
Citation#
A Citation records the scholarly provenance of a claim, linking a subject object to a source with full bibliographic detail.
Fields: id, subject (kind, objectId, selector), source (kind:
manuscript | edition | translation | article | book | lexicon | database,
title, authors, year, url, doi, shelfmark), locator (page,
folio, line, section), style (CitationStyle), formatted,
rightsStatus, verification (state, verifiedAt, scholarProfileId),
timestamps.
ScholarProfile#
A ScholarProfile establishes a scholar's credentials, areas of expertise, and review authority — determining what they can approve (editions, translations, citations) and at what risk level.
Fields: id, userId, displayName, publicBio (nullable), credentials
({ credentialId, kind, institution, field, verified, verifiedAt }[]),
areasOfExpertise (1–50), languages (1–40), attributionPreference
(full-name | initials | institutional | anonymous-review),
disclosureControls (showCredentials, showInstitution,
showReviewHistory), reviewAuthority (canApproveEditions,
canApproveTranslations, canVerifyCitations, maxReviewRisk:
low | medium | high), timestamps.
4.3 V1 contract invariants#
The Zod contracts in libs/contracts/src/nisaba/index.ts use superRefine to
enforce cross-field and cross-entity consistency rules. These invariants go
beyond field-level validation to express scholarly and operational requirements.
- Manuscript — digitized/iiif manuscripts require
imageManifestUrl; non-public-domain manuscripts requirerights.licenseLabel;dateRange.notAftercannot precedenotBefore;relatedPassageIdsunique. - Edition —
apparatuswitness ids must be declared inmanuscriptIds; published editions requirepublicationDate; approved editions require reviewer identity +reviewedAt; id arrays unique. - Translation —
sourceLanguage≠targetLanguage; approved translations require reviewer identity +reviewedAt. - Passage — segments strictly ordered and non-overlapping; published passages require ≥ 1 source citation; all id arrays unique.
- LexiconEntry — entries cannot relate to themselves;
roots/glosses/id arrays unique. - MorphologyEntry —
humanparsing method requiresreviewerScholarProfileId;featureskeys unique. - Annotation — non-
highlightannotations requirebody;segmentandtokentargets require a selector. - ConceptGraphNode/Edge — edges cannot self-loop;
high-confidence edges require evidence passages or citations. - Notebook —
sharednotebooks require ≥ 2 collaborators; id arrays unique. - StudyPlan — steps strictly ordered;
activeplans requirestartedAt;completedplans requirecompletedAt. - Citation — approved citations require
verifiedAt+scholarProfileId. - ScholarProfile — verified credentials require
verifiedAt; citation verification authority requires ≥ 1 verified credential.
Exported helper predicates: isPublishedPassage, conceptEdgeRequiresEvidence,
scholarCanVerifyCitations.
5. Scholarly SDK (@nisaba/client)#
libs/nisaba/client/src/api-client.ts is a separate, zero-dependency TypeScript
SDK (NisabaClient, built via NisabaClientBuilder) that targets a broader
scholarly API surface than the V1 contract API above. It is exported from
@nisaba/client as the apiClient namespace, alongside a reactHooks
namespace (react-hooks.ts).
The SDK exists because the V1 contract API is intentionally minimal and stable, while the scholarly API needs richer operations like stemma queries, full collation management, and AI assistant invocations that are not yet part of the versioned public contract.
5.1 SDK resource operations#
All paths are relative to the configured baseUrl. The operations are organized
by the scholarly domain they serve:
| Area | Methods | Paths |
|---|---|---|
| Manuscripts | getManuscript, listManuscripts, createManuscript, updateManuscript (PATCH), deleteManuscript, getManuscriptWitnesses, addWitness, getManuscriptFolios, searchManuscripts |
/manuscripts, /manuscripts/{id}, /manuscripts/{id}/witnesses, /manuscripts/{id}/folios, /manuscripts/search |
| Collation | getCollation, listCollations, createCollation, runCollation, getCollationResult, getVariantUnits, classifyVariant, getApparatus, getStemma |
/collations, /collations/{id}, /variants/{id} |
| Annotations | getAnnotation, listAnnotations, createAnnotation, updateAnnotation, deleteAnnotation, getAnnotationsForDocument, getAnnotationsForPassage, batchCreateAnnotations, getAnnotationLayers |
/annotations, /annotations/{id}, /annotations/batch, /documents/{id} |
| Editions | getEdition, listEditions, createEdition, updateEdition, publishEdition, getEditionApparatus, getEditionTranslation, exportEdition |
/editions, /editions/{id} |
| References | resolveReference, parseReference, getPassage, listCanonicalWorks, getWorkStructure, getParallelPassages |
/references/resolve, /references/parse, /passages, /passages/parallels, /works, /works/{id} |
| Corpus search | searchCorpus, searchWithFacets, getSuggestions |
/search, /search/faceted, /search/suggestions |
| Comparative | getConceptMap, listConceptMaps, createConceptMap, getConceptParallelPassages, getInfluenceNetwork, getMotifAttestations |
/concept-maps, /concept-maps/{id}, /concept-maps/influence-network, /concepts/{id}, /motifs/{id} |
| AI assistant | invokeTranslationAssistant, invokeCommentaryGenerator, invokeVariantEvaluator, invokeResearchAssistant |
/ai/translate, /ai/commentary, /ai/evaluate-variant, /ai/research |
| Batch / WS | batchRequests, connectWebSocket |
— |
Generic HTTP verbs are also public: get, post, put, patch, delete.
5.2 SDK behavior#
The SDK is designed to be resilient and cache-aware, which matters for scholarly use cases where large reference datasets (lexicon entries, canonical reference tables) are accessed repeatedly across a session.
Error handling uses a typed error class hierarchy:
NisabaErrorCodeenum values:BAD_REQUEST, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, CONFLICT, VALIDATION_ERROR, RATE_LIMITED, INTERNAL_ERROR, TIMEOUT, NETWORK_ERROR, PARSE_ERROR, ABORTED, SERVICE_UNAVAILABLE, UNKNOWN. Errors surface asNisabaApiErrorwithcode,status,details?,validationErrors?,retryAfterMs?.
Operational defaults and retry policy:
- Defaults: 30 s timeout, 3 retries, 500 ms base backoff, 5-minute cache TTL.
- Retryable HTTP methods:
GET, HEAD, OPTIONS, PUT, DELETE. - Retryable status codes:
408, 429, 500, 502, 503, 504.
Infrastructure features:
- In-memory
ResponseCachewith configurable TTL and prefix invalidation. - Offset (
PaginationParams) and cursor (CursorPaginationParams) pagination. - Request/response interceptors for authentication, logging, and transformation.
NisabaClientEventsevent emitter for monitoring.connectWebSocket(channel, config?)for real-time collaboration channels.
The SDK type surface includes: Witness, Folio, Collation,
CollationResult, Apparatus, Stemma/StemmaNode/StemmaEdge,
VariantUnit, Reading, ConceptMap, InfluenceNetwork, MotifAttestation,
AI request/response interfaces (CommentaryGeneratorParams,
VariantEvaluatorResponse, etc.), and WebSocketMessage<T>.
The SDK's collation/stemma/AI endpoints describe the scholarly API the
@nisaba/clientpackage targets. The currently generated and served REST contract is the 13-resource V1 surface in §4; the two surfaces are not yet unified.
6. Domain Error Model (@nisaba/core)#
Source: libs/nisaba/core/src/errors.ts. Nisaba's errors are structured rather
than generic strings, which allows API middleware to map them to appropriate
HTTP status codes and allows client code to handle specific error conditions.
The error classes extend @oshun/errors base classes, so Oshun-wide error
handling middleware recognizes them.
The NISABA_ERROR_CODES registry groups error codes by domain area (all
prefixed NISABA_):
- Manuscript (
MANUSCRIPT_NOT_FOUND,MANUSCRIPT_ALREADY_EXISTS,MANUSCRIPT_INVALID_SIGLUM) - Collation (
COLLATION_NOT_FOUND,COLLATION_INVALID_CONFIG,COLLATION_ALIGNMENT_FAILED,COLLATION_WITNESS_MISSING) - Variant (
VARIANT_NOT_FOUND,VARIANT_INVALID_CLASSIFICATION,VARIANT_OVERLAP_DETECTED) - Edition (
EDITION_NOT_FOUND,EDITION_ALREADY_PUBLISHED,EDITION_INVALID_APPARATUS) - Annotation (
ANNOTATION_NOT_FOUND,ANNOTATION_INVALID_TARGET,ANNOTATION_INVALID_SELECTOR,ANNOTATION_LAYER_NOT_FOUND) - Reference (
REFERENCE_NOT_FOUND,REFERENCE_INVALID_FORMAT,REFERENCE_AMBIGUOUS,REFERENCE_OUT_OF_RANGE,REFERENCE_RESOLUTION_FAILED) - Language (
LANGUAGE_NOT_SUPPORTED,LANGUAGE_PARSE_FAILED,MORPHOLOGY_PARSE_FAILED,TRANSLITERATION_FAILED,LEXICON_LOOKUP_FAILED,NORMALIZATION_FAILED,ALIGNMENT_FAILED) - Comparative (
MAPPING_NOT_FOUND,CONCEPT_MAPPING_FAILED,MAPPING_CYCLE_DETECTED,INFLUENCE_EDGE_INVALID) - Paleography (
ANALYSIS_NOT_FOUND,ANALYSIS_INVALID_FEATURES,PALEOGRAPHIC_ANALYSIS_FAILED,DATE_ESTIMATION_FAILED,HAND_NOT_FOUND) - Corpus (
CORPUS_NOT_FOUND,CORPUS_IMPORT_FAILED,CORPUS_EXPORT_FAILED,CORPUS_CONNECTION_FAILED,TEI_PARSE_FAILED) - External API (
EXTERNAL_API_ERROR,EXTERNAL_API_RATE_LIMITED,EXTERNAL_API_TIMEOUT,IIIF_FAILED) - Critical edition (
APPARATUS_GENERATION_FAILED) - Unicode/encoding (
UNICODE_INVALID_SEQUENCE,ENCODING_CONVERSION_FAILED,OFFSET_OUT_OF_BOUNDS) - Workspace (
PROJECT_NOT_FOUND,BOOKMARK_NOT_FOUND,LIBRARY_ITEM_NOT_FOUND)
The concrete error classes (each extending an @oshun/errors base):
ManuscriptNotFoundError, ManuscriptAlreadyExistsError,
CollationNotFoundError, CollationAlignmentError, WitnessMissingError,
VariantNotFoundError, VariantOverlapError, EditionNotFoundError,
EditionAlreadyPublishedError, AnnotationNotFoundError,
AnnotationInvalidTargetError, AnnotationLayerNotFoundError,
ReferenceNotFoundError, ReferenceFormatError, ReferenceAmbiguousError,
ReferenceResolutionError, LanguageNotSupportedError, MorphologyParseError,
TransliterationError, LexiconLookupError, AlignmentError,
NormalizationError, CollationError, ApparatusGenerationError,
PaleographicAnalysisError, DateEstimationError, ConceptMappingError,
CorpusConnectionError, TEIParseError, IIIFError, ExternalApiError,
ExternalApiRateLimitError, ExternalApiTimeoutError,
UnicodeInvalidSequenceError, OffsetOutOfBoundsError.
AncientTextErrorContext carries optional diagnostic fields that can be
attached to any error: language, script, sourceText, position,
reference, corpus, manuscriptId, projectId, apiName, operation. Type
guards: isNisabaError, isRetryableNisabaError.
7. Canonical URI Scheme#
Nisaba's canonical URI scheme gives every passage in every tradition a single, stable, dereferenceable identifier that works across all corpus connectors, canon systems, and the cross-domain bridge.
@nisaba/core (core/src/utils/references.ts) builds and parses nisaba://
URIs. The format is:
nisaba://tradition/canon/book[/chapter[/verse[-verseEnd]]], where each segment
is URI-encoded. Example: nisaba://Greek%20Philosophy/Classical/republic/514a.
@nisaba/canon (canon/src/canonical-uri.ts) documents the canonical form as
nisaba://tradition/work/reference, with representative examples:
nisaba://bible/protestant/Gen.1.1 and nisaba://hindu/gita/2.47.
parseNisabaUri / parseUri decode a URI back to its components for display
and database lookup.
8. Cross-Domain Contract (@nisaba/cross-domain)#
libs/nisaba/cross-domain/src/nisaba-cross-domain.ts defines the typed
interface through which other Oshun domains consume Nisaba research outputs. The
boundary is important: Nisaba owns the scholarly text layer; Tara, Arete,
Veritas, and Nyx each own their own UX and data model but read-link to Nisaba
entities rather than duplicating them.
The cross-domain types:
NisabaCrossDomainCapability— names the six capabilities Nisaba exposes to other domains:tara-passage-companions, arete-study-plans, veritas-source-depth, nyx-cosmology-overlays, shared-concept-graph, domain-to-domain-recommendationsNisabaBridgeDomain— the domains Nisaba bridges to:tara, arete, veritas, nyx, iris, nisaba- Signal interfaces describe the data payloads that cross each boundary:
NisabaPassageSignal,TaraPracticeSignal,VeritasSourceDepthSignal,NyxCosmologySignal,NisabaConceptGraphSignal - Builder functions construct the typed link objects for each direction:
buildNisabaCrossDomainBridge,buildTaraPassageCompanionLinks,buildAreteStudyPlanLinks,buildVeritasSourceDepthLinks,buildNyxCosmologyOverlayLinks,buildSharedConceptGraphLinks,buildDomainRecommendationLinks verifyNisabaCrossDomainCoveragechecks that all required capabilities are covered;REQUIRED_NISABA_CROSS_DOMAIN_CAPABILITIESenumerates the full validated set
9. Mobile Surface (@nisaba/mobile)#
libs/nisaba/mobile/src/mobile-study.ts defines the mobile-specific study
surface for Nisaba. It specifies which features are available on mobile, the
routes those features live at, and the data shapes used by mobile clients.
NisabaMobileFeature— the 12 features available on mobile:domain-home, reading-queue, daily-passage, compact-highlight-flow, annotation-flow, quick-compare, glossary-lookup, morphology-lookup, saved-manuscripts, saved-editions, study-reminders, assistant-assisted-explanationNisabaMobileRoute— the 7 mobile routes:/domains/nisaba,/mobile/nisaba/queue,/mobile/nisaba/daily,/mobile/nisaba/read/:passageId,/mobile/nisaba/compare/:passageId,/mobile/nisaba/saved,/mobile/nisaba/studyNisabaMobileArtifactKind—manuscript, edition- Data interfaces:
NisabaMobilePassage,NisabaMobileGlossaryEntry,NisabaMobileMorphologyEntry,NisabaMobileSavedArtifact,NisabaMobileStudyReminderRule
10. Study Plans (@nisaba/study-plans)#
libs/nisaba/study-plans/src/study-plans.ts defines the data model for
structured learning paths through Nisaba's texts — used both by the Nisaba
workspace and by the Arete cross-domain bridge.
NisabaStudyPlanCadence—daily, weekly, intensive, self_pacedNisabaStudyPlanStatus—draft, active, paused, completed, archivedNisabaStudyPlanDifficulty—introductory, developing, advanced, expertNisabaCompletionForecast—on_track, at_risk, blocked, completed- Additional enums:
NisabaStudyPlanObjectiveKind,NisabaStudyResourceKind,NisabaStudyStepKind - Interface:
NisabaStudyPlanObjective
11. Encoding & Interoperability Standards#
Nisaba implements a specific set of international encoding and interchange standards. Compliance with these standards is what makes Nisaba data interoperable with external digital humanities infrastructure — Perseus, CDLI, CBETA, and other platforms all expect these formats.
The standards implemented in @nisaba/standards (text-encoding-standards.ts,
reference-linked-data.ts) and @nisaba/corpora:
| Standard | Usage |
|---|---|
| ISO 15924 | Script codes backing WritingSystem enum values |
| Unicode NFC | Text normalization (core/src/utils/unicode.ts) |
| TEI P5 / EpiDoc | Critical edition and corpus interchange (corpora/src/tei-xml-parser.ts) |
| W3C WADM | Annotation data model (@nisaba/annotations) |
| ATF | Cuneiform interchange (corpora/src/atf-parser.ts) |
| CTS/CITE | Canonical reference interoperability (canon/src/cts-cite.ts) |
| Leiden Conventions | Epigraphic markup (criticism/src/leiden-conventions.ts) |
| IIIF | Manuscript image manifests (criticism/src/iiif-linking.ts) |
Annotation export formats: w3c, json, csv, tei
(AnnotationExportSchema). Citation styles in the V1 contract: chicago,
mla, apa, sbl, cts, custom.
12. Package Inventory#
The full set of 22 publishable @nisaba/* packages under libs/nisaba/ (all at
version 0.1.0):
annotations, api-client, assistant, canon, client, comparative,
core, corpora, criticism, cross-domain, database, editions,
geotemporal, languages, mobile, paleography, philology, schemas,
standards, study-plans, translations, workspace.
See architecture.md for the dependency layering and per-package internals.