Domain · Specifications

Nisaba — Technical Specifications

Source: libs/nisaba/core/src/types/.

12sections27 minread

On this page

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:

  1. Canonical V1 contracts (libs/contracts/src/nisaba/) — the schemas the generated REST API (@nisaba/api-client) is built from.
  2. @nisaba/schemas — Zod schemas used by domain logic and the Prisma-backed persistence layer.
  3. @nisaba/core types — 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:

  • PartOfSpeechnoun, verb, adjective, adverb, pronoun, preposition, conjunction, particle, interjection, article, numeral, determiner, auxiliary, postposition, classifier, ideogram, unknown
  • GrammaticalGendermasculine, feminine, neuter, common, animate, inanimate
  • GrammaticalNumbersingular, dual, trial, plural, collective
  • GrammaticalPersonfirst, second, third
  • GrammaticalCasenominative, accusative, genitive, dative, ablative, vocative, locative, instrumental, ergative, absolutive, construct, oblique
  • VerbTenseAspectpresent, past, future, aorist, perfect, pluperfect, imperfect, future_perfect, preterite, stative, durative, punctual
  • VerbMoodindicative, subjunctive, optative, imperative, jussive, cohortative, precative, prohibitive, infinitive, participle
  • VerbVoiceactive, passive, middle, medio-passive, causative, reflexive
  • VerbStem — Hebrew (qal, niphal, piel, pual, hiphil, hophal, hithpael), Akkadian (G, D, S, N, Gt, Dt, St, Nt), Arabic (form_Iform_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.

  • ReferenceSystemType enumerates 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, custom
  • CanonicalReferenceSystem (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 computed uri
  • CanonicalRefRange groups a start and end CanonicalRef with a human-readable displayString

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, OTHER
  • VariantClassificationType — 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_PLUS
  • VariantClassification — same 22 values as VariantClassificationType
  • ApparatusReading (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 its reference, lemma, all readings (readonly ApparatusReading[]), and significance score (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, TRANSCRIPTION
  • AnnotationMotivation — 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 type AnnotationSelector

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, ICONOGRAPHIC
  • EvidenceGradeType — how strongly the evidence supports a claim. Values: CERTAIN, HIGHLY_PROBABLE, PROBABLE, POSSIBLE, UNCERTAIN, SPECULATIVE, DISPUTED
  • ConsensusLevelType — how widely the scholarly community agrees with a claim. Values: UNIVERSAL, STRONG, MAJORITY, DIVIDED, MINORITY, INDIVIDUAL, UNKNOWN
  • ComparativeEvidence (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 via deletedAt.
  • VariantUnitCollationProject (onDelete: Cascade); optional manuscript relation.
  • CriticalEdition → optional CollationProject relation.
  • Annotation → optional AnnotationLayer and Manuscript relations; soft delete via deletedAt.
  • 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.
  • PaleographicAnalysisManuscript (onDelete: Cascade); has scribalHands.
  • ScribalHandManuscript (onDelete: Cascade); optional analysis relation.
  • 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.
  • WitnessClassificationSchematextualFamily?, textType?, reliability? (0–1), completeness? (0–1), notes?.
  • ManuscriptSchemaid?, 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 plus limit (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).
  • VariantReadingSchematext, witnesses (string[]), isPreferred, classification?, cause?, note?.
  • VariantUnitSchemaid?, collationProjectId, reference, startOffset/endOffset (int ≥ 0), baseReading, lemma?, readings, classification?, cause?, significance (0–10), preferredReading?, rationale?, evidenceGrade?, manuscriptId?, notes?, metadata. Refinement: endOffset >= startOffset.
  • CollationConfigSchemaalgorithm (needleman-wunsch | smith-waterman | gotoh | medite | collatex), matchScore, mismatchPenalty, gapPenalty, normalizeUnicode, caseSensitive, ignoreAccents, ignorePunctuation, tokenizer (word | character | morpheme).
  • CollationResultSchemaprojectId, totalVariantUnits, significantVariants, agreementPercentage (0–100), witnesses, executionTimeMs?.
  • CollationProjectSchemaid?, name, description?, baseText?, witnesses, collationMethod?, config?, status (ProjectStatus, default PLANNING), 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).
  • ApparatusReadingSchematext, witnesses, isPreferred, classification?, note?.
  • ApparatusEntrySchemareference, lemma, readings (min 1), significance (0–10), note?.
  • ApparatusConfigSchemaformat (default POSITIVE), includeOrthographic, minimumSignificance (0–10), showWitnessDescriptions, groupByFamily, language.
  • CriticalEditionSchemaid?, title, description?, version, collationProjectId?, text, apparatus, apparatusFormat, status (EditionStatus, default DRAFT), 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 union AnnotationSelectorSchema.
  • AnnotationSchemaid?, targetUri, targetType, targetSelector?, type, body, bodyFormat (default text/plain), language?, motivation?, status (default ACTIVE), layerId?, manuscriptId?, tags, metadata, ownerId, projectId?.
  • AnnotationLayerSchemaid?, name, description?, color?, scope?, permissions, metadata, ownerId.
  • AnnotationExportSchemaformat (w3c | json | csv | tei, default w3c), 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).
  • CanonicalReferenceSchemaid?, tradition, canon, collection?, bookId, bookName, bookAbbreviation?, alternateNames, chapterCount?, verseCount?, structure?, canonicalOrder, originalLanguage?, languages, versificationScheme?, versificationMap?, externalIds, metadata.
  • VersificationMappingSchemasourceScheme, targetScheme, bookId, mappings ({ sourceChapter, sourceVerse, targetChapter, targetVerse, note? }[]).
  • ReferenceRangeSchemastartTradition/startCanon/startBook plus optional chapter/verse, optional end fields.
  • ReferenceQuerySchematradition?, 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 (default POSSIBLE), consensusLevel (default UNKNOWN), evidence (typed array), bibliography, notes?, metadata, ownerId.
  • MotifSchemaid?, motifId, motifName, motifCategory?, tradition, textReference, passage?, language?, function?, context?, dating?, evidenceGrade (default PROBABLE), bibliography, metadata, ownerId.
  • InfluenceEdgeSchemaid?, sourceId/sourceType/sourceTradition, targetId/targetType/targetTradition, influenceType, direction (forward | reverse | bidirectional | uncertain, default forward), 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.

  • CorpusMetadataSchemaid?, name, description?, tradition?, language, writingSystem?, dateRange? ({ earliest, latest }), textCount, tokenCount, genre?, source?, license?, version, format (plain | tei | conll | json | xml), encoding (default utf-8), metadata, ownerId.
  • PaleographicFeatureSchemafeatureName, featureCategory (letter_form, stroke_pattern, ductus, angle, proportion, spacing, decoration, ligature, abbreviation, ruling, other), value, description?, confidence (0–1), reference?.
  • DateEstimationSchemadateEarliest/dateLatest, confidence (EvidenceGrade), method (paleographic, radiocarbon, archaeological, historical, stylistic, colophon, other), comparanda, rationale?. Refinement: dateLatest >= dateEarliest.
  • ScribalHandSchemaid?, manuscriptId, analysisId?, handLabel, handDescription?, folio range fields, scriptStyle?, characteristics, letterForms, dateEstimate?, dateConfidence?, scribeName?, scribeIdentification?, notes?, metadata.
  • PaleographicAnalysisSchemaid?, 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.

  • FuzzyDateSchemaearliest/latest (int), confidence (0–1), label?, calendar (gregorian, julian, hebrew, islamic, buddhist, other, default gregorian). Refinement: latest >= earliest.
  • ProvenanceEventSchemadate? (FuzzyDate), location?, event (created, copied, acquired, sold, donated, stolen, discovered, restored, transferred, other), description?, actor?, source?, confidence (EvidenceGrade, default PROBABLE).
  • ProvenanceChainSchemamanuscriptId, events, notes?, bibliography, metadata.
  • HistoricalLocationSchemaid?, 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.
  • TimelineEventSchemaid?, 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.
  • GeospatialQuerySchemalatitude/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:

  • NisabaScriptlatin, greek, hebrew, arabic, devanagari, pali-sinhala, coptic, cuneiform, tibetan, chinese, japanese, syriac, ethiopic, other
  • TextDirectionltr, rtl, vertical, boustrophedon
  • TextFormatplain-text, markdown, tei-xml, html
  • PassageStatusdraft, review, published, archived
  • ReviewStateunreviewed, in-review, approved, rejected
  • PartOfSpeechnoun, verb, adjective, adverb, pronoun, particle, preposition, conjunction, interjection, numeral, proper-noun, unknown
  • MorphologyFeaturecase, number, gender, person, tense, aspect, mood, voice, state, degree, stem, root, prefix, suffix
  • CitationStylechicago, mla, apa, sbl, cts, custom
  • RightsStatuspublic-domain, open-license, licensed, restricted, unknown
  • ScholarCredentialKindacademic-degree, faculty-appointment, editorial-role, translator-credit, institutional-affiliation, community-expert
  • CanonicalReferencescheme (cts | osis | sefaria | library-of-congress | custom), reference, normalizedReference, urn (nullable), workId (slug), workTitle, divisionPath (≤ 12 entries)
  • TextRangeSelectorsegmentId (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. PassageSegmentsegmentId, 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. ApparatusEntryentryId, 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 require rights.licenseLabel; dateRange.notAfter cannot precede notBefore; relatedPassageIds unique.
  • Editionapparatus witness ids must be declared in manuscriptIds; published editions require publicationDate; approved editions require reviewer identity + reviewedAt; id arrays unique.
  • TranslationsourceLanguagetargetLanguage; 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.
  • MorphologyEntryhuman parsing method requires reviewerScholarProfileId; features keys unique.
  • Annotation — non-highlight annotations require body; segment and token targets require a selector.
  • ConceptGraphNode/Edge — edges cannot self-loop; high-confidence edges require evidence passages or citations.
  • Notebookshared notebooks require ≥ 2 collaborators; id arrays unique.
  • StudyPlan — steps strictly ordered; active plans require startedAt; completed plans require completedAt.
  • 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:

  • NisabaErrorCode enum 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 as NisabaApiError with code, 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 ResponseCache with configurable TTL and prefix invalidation.
  • Offset (PaginationParams) and cursor (CursorPaginationParams) pagination.
  • Request/response interceptors for authentication, logging, and transformation.
  • NisabaClientEvents event 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/client package 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-recommendations
  • NisabaBridgeDomain — 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
  • verifyNisabaCrossDomainCoverage checks that all required capabilities are covered; REQUIRED_NISABA_CROSS_DOMAIN_CAPABILITIES enumerates 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-explanation
  • NisabaMobileRoute — 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/study
  • NisabaMobileArtifactKindmanuscript, 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.

  • NisabaStudyPlanCadencedaily, weekly, intensive, self_paced
  • NisabaStudyPlanStatusdraft, active, paused, completed, archived
  • NisabaStudyPlanDifficultyintroductory, developing, advanced, expert
  • NisabaCompletionForecaston_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.