@nakafa/aksara-contracts 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/LICENSE +185 -0
  2. package/README.md +73 -0
  3. package/dist/artifact/integrity.d.ts +29 -0
  4. package/dist/artifact/integrity.js +54 -0
  5. package/dist/artifact/limits.d.ts +26 -0
  6. package/dist/artifact/limits.js +46 -0
  7. package/dist/artifact/source.d.ts +21 -0
  8. package/dist/artifact/source.js +24 -0
  9. package/dist/artifact/spec.d.ts +148 -0
  10. package/dist/artifact/spec.js +92 -0
  11. package/dist/artifact/verify.d.ts +26 -0
  12. package/dist/artifact/verify.js +18 -0
  13. package/dist/cache/content.d.ts +52 -0
  14. package/dist/cache/content.js +80 -0
  15. package/dist/content.d.ts +168 -0
  16. package/dist/content.js +107 -0
  17. package/dist/country.d.ts +4 -0
  18. package/dist/country.js +8 -0
  19. package/dist/date.d.ts +24 -0
  20. package/dist/date.js +44 -0
  21. package/dist/decode.d.ts +4 -0
  22. package/dist/decode.js +8 -0
  23. package/dist/delivery.d.ts +4 -0
  24. package/dist/delivery.js +7 -0
  25. package/dist/errors.d.ts +10 -0
  26. package/dist/errors.js +8 -0
  27. package/dist/graph/family.d.ts +45 -0
  28. package/dist/graph/family.js +85 -0
  29. package/dist/graph/identity.d.ts +19 -0
  30. package/dist/graph/identity.js +39 -0
  31. package/dist/graph/spec.d.ts +20 -0
  32. package/dist/graph/spec.js +26 -0
  33. package/dist/hash/text.d.ts +10 -0
  34. package/dist/hash/text.js +20 -0
  35. package/dist/ids.d.ts +27 -0
  36. package/dist/ids.js +63 -0
  37. package/dist/limits.d.ts +10 -0
  38. package/dist/limits.js +10 -0
  39. package/dist/locale.d.ts +37 -0
  40. package/dist/locale.js +53 -0
  41. package/dist/material/domain.d.ts +4 -0
  42. package/dist/material/domain.js +8 -0
  43. package/dist/preview/artifact.d.ts +198 -0
  44. package/dist/preview/artifact.js +20 -0
  45. package/dist/preview/auth.d.ts +71 -0
  46. package/dist/preview/auth.js +49 -0
  47. package/dist/preview/document.d.ts +692 -0
  48. package/dist/preview/document.js +90 -0
  49. package/dist/preview/spec.d.ts +2517 -0
  50. package/dist/preview/spec.js +142 -0
  51. package/dist/preview/target.d.ts +172 -0
  52. package/dist/preview/target.js +70 -0
  53. package/dist/program/curriculum.d.ts +69 -0
  54. package/dist/program/curriculum.js +181 -0
  55. package/dist/program/snapshot/digest.d.ts +26 -0
  56. package/dist/program/snapshot/digest.js +220 -0
  57. package/dist/program/snapshot/hash.d.ts +31 -0
  58. package/dist/program/snapshot/hash.js +40 -0
  59. package/dist/program/snapshot/row-hash.d.ts +155 -0
  60. package/dist/program/snapshot/row-hash.js +34 -0
  61. package/dist/program/snapshot/row.d.ts +139 -0
  62. package/dist/program/snapshot/row.js +28 -0
  63. package/dist/program/snapshot/spec.d.ts +36 -0
  64. package/dist/program/snapshot/spec.js +39 -0
  65. package/dist/program/spec.d.ts +85 -0
  66. package/dist/program/spec.js +197 -0
  67. package/dist/projection/article.d.ts +145 -0
  68. package/dist/projection/article.js +150 -0
  69. package/dist/projection/digest.d.ts +261 -0
  70. package/dist/projection/digest.js +59 -0
  71. package/dist/projection/hash.d.ts +3 -0
  72. package/dist/projection/hash.js +10 -0
  73. package/dist/projection/material.d.ts +109 -0
  74. package/dist/projection/material.js +160 -0
  75. package/dist/projection/page.d.ts +112 -0
  76. package/dist/projection/page.js +106 -0
  77. package/dist/projection/question.d.ts +520 -0
  78. package/dist/projection/question.js +109 -0
  79. package/dist/projection/spec.d.ts +503 -0
  80. package/dist/projection/spec.js +56 -0
  81. package/dist/projection/verify.d.ts +281 -0
  82. package/dist/projection/verify.js +86 -0
  83. package/dist/question/identity.d.ts +175 -0
  84. package/dist/question/identity.js +205 -0
  85. package/dist/question/item.d.ts +453 -0
  86. package/dist/question/item.js +146 -0
  87. package/dist/question/response.d.ts +175 -0
  88. package/dist/question/response.js +150 -0
  89. package/dist/quran/attribution.d.ts +48 -0
  90. package/dist/quran/attribution.js +44 -0
  91. package/dist/quran/identity.d.ts +105 -0
  92. package/dist/quran/identity.js +100 -0
  93. package/dist/quran/notes.d.ts +56 -0
  94. package/dist/quran/notes.js +142 -0
  95. package/dist/quran/provenance.d.ts +257 -0
  96. package/dist/quran/provenance.js +144 -0
  97. package/dist/quran/snapshot/digest.d.ts +33 -0
  98. package/dist/quran/snapshot/digest.js +232 -0
  99. package/dist/quran/snapshot/hash.d.ts +51 -0
  100. package/dist/quran/snapshot/hash.js +50 -0
  101. package/dist/quran/snapshot/row/hash.d.ts +748 -0
  102. package/dist/quran/snapshot/row/hash.js +115 -0
  103. package/dist/quran/snapshot/row.d.ts +354 -0
  104. package/dist/quran/snapshot/row.js +91 -0
  105. package/dist/quran/snapshot/spec.d.ts +50 -0
  106. package/dist/quran/snapshot/spec.js +66 -0
  107. package/dist/quran/source.d.ts +206 -0
  108. package/dist/quran/source.js +153 -0
  109. package/dist/quran/spec.d.ts +47 -0
  110. package/dist/quran/spec.js +41 -0
  111. package/dist/quran/text.d.ts +7 -0
  112. package/dist/quran/text.js +11 -0
  113. package/dist/release/canonical.d.ts +23 -0
  114. package/dist/release/canonical.js +29 -0
  115. package/dist/release/current/evidence.d.ts +424 -0
  116. package/dist/release/current/evidence.js +41 -0
  117. package/dist/release/current/runtime.d.ts +4 -0
  118. package/dist/release/current/runtime.js +15 -0
  119. package/dist/release/current/state.d.ts +567 -0
  120. package/dist/release/current/state.js +91 -0
  121. package/dist/release/digest.d.ts +54 -0
  122. package/dist/release/digest.js +71 -0
  123. package/dist/release/hash.d.ts +72 -0
  124. package/dist/release/hash.js +14 -0
  125. package/dist/release/head.d.ts +206 -0
  126. package/dist/release/head.js +131 -0
  127. package/dist/release/items.d.ts +98 -0
  128. package/dist/release/items.js +114 -0
  129. package/dist/release/lifecycle.d.ts +297 -0
  130. package/dist/release/lifecycle.js +97 -0
  131. package/dist/release/origin.d.ts +30 -0
  132. package/dist/release/origin.js +24 -0
  133. package/dist/release/policy.d.ts +45 -0
  134. package/dist/release/policy.js +124 -0
  135. package/dist/release/result/digest.d.ts +127 -0
  136. package/dist/release/result/digest.js +140 -0
  137. package/dist/release/result/spec.d.ts +4 -0
  138. package/dist/release/result/spec.js +5 -0
  139. package/dist/release/rollback/digest.d.ts +126 -0
  140. package/dist/release/rollback/digest.js +92 -0
  141. package/dist/release/rollback/spec.d.ts +1729 -0
  142. package/dist/release/rollback/spec.js +156 -0
  143. package/dist/release/route/digest.d.ts +45 -0
  144. package/dist/release/route/digest.js +59 -0
  145. package/dist/release/route/page.d.ts +56 -0
  146. package/dist/release/route/page.js +46 -0
  147. package/dist/release/route/spec.d.ts +49 -0
  148. package/dist/release/route/spec.js +40 -0
  149. package/dist/release/route/verify.d.ts +66 -0
  150. package/dist/release/route/verify.js +67 -0
  151. package/dist/release/signing.d.ts +6 -0
  152. package/dist/release/signing.js +38 -0
  153. package/dist/release/snapshot/data.d.ts +475 -0
  154. package/dist/release/snapshot/data.js +74 -0
  155. package/dist/release/snapshot/evidence-requirement.d.ts +22 -0
  156. package/dist/release/snapshot/evidence-requirement.js +21 -0
  157. package/dist/release/snapshot/evidence.d.ts +58 -0
  158. package/dist/release/snapshot/evidence.js +14 -0
  159. package/dist/release/snapshot/program-evidence.d.ts +17 -0
  160. package/dist/release/snapshot/program-evidence.js +39 -0
  161. package/dist/release/snapshot/quran-evidence.d.ts +27 -0
  162. package/dist/release/snapshot/quran-evidence.js +43 -0
  163. package/dist/release/snapshot/scope.d.ts +60 -0
  164. package/dist/release/snapshot/scope.js +102 -0
  165. package/dist/release/snapshot/spec.d.ts +193 -0
  166. package/dist/release/snapshot/spec.js +139 -0
  167. package/dist/release/snapshot/tryout-evidence.d.ts +22 -0
  168. package/dist/release/snapshot/tryout-evidence.js +86 -0
  169. package/dist/release/snapshot/verify.d.ts +710 -0
  170. package/dist/release/snapshot/verify.js +147 -0
  171. package/dist/release/spec.d.ts +491 -0
  172. package/dist/release/spec.js +200 -0
  173. package/dist/release/verify.d.ts +98 -0
  174. package/dist/release/verify.js +70 -0
  175. package/dist/renderer/compatibility.d.ts +35 -0
  176. package/dist/renderer/compatibility.js +48 -0
  177. package/dist/renderer/component.d.ts +99 -0
  178. package/dist/renderer/component.js +102 -0
  179. package/dist/renderer/contract.d.ts +144 -0
  180. package/dist/renderer/contract.js +122 -0
  181. package/dist/renderer/domain.d.ts +6 -0
  182. package/dist/renderer/domain.js +18 -0
  183. package/dist/renderer/manifest.d.ts +86 -0
  184. package/dist/renderer/manifest.js +49 -0
  185. package/dist/renderer/selection.d.ts +39 -0
  186. package/dist/renderer/selection.js +87 -0
  187. package/dist/runtime/error.d.ts +8 -0
  188. package/dist/runtime/error.js +20 -0
  189. package/dist/runtime/protected/limits.d.ts +10 -0
  190. package/dist/runtime/protected/limits.js +15 -0
  191. package/dist/runtime/protected/spec.d.ts +328 -0
  192. package/dist/runtime/protected/spec.js +79 -0
  193. package/dist/runtime/protected/verify.d.ts +97 -0
  194. package/dist/runtime/protected/verify.js +72 -0
  195. package/dist/runtime/result.d.ts +12 -0
  196. package/dist/runtime/result.js +17 -0
  197. package/dist/runtime/spec.d.ts +705 -0
  198. package/dist/runtime/spec.js +61 -0
  199. package/dist/runtime/verify.d.ts +479 -0
  200. package/dist/runtime/verify.js +123 -0
  201. package/dist/signature/spec.d.ts +53 -0
  202. package/dist/signature/spec.js +29 -0
  203. package/dist/signature/trusted.d.ts +19 -0
  204. package/dist/signature/trusted.js +32 -0
  205. package/dist/signature/verify.d.ts +10 -0
  206. package/dist/signature/verify.js +82 -0
  207. package/dist/text/order.d.ts +2 -0
  208. package/dist/text/order.js +10 -0
  209. package/dist/text/syntax.d.ts +6 -0
  210. package/dist/text/syntax.js +15 -0
  211. package/dist/transport/batch.d.ts +971 -0
  212. package/dist/transport/batch.js +101 -0
  213. package/dist/transport/failure.d.ts +168 -0
  214. package/dist/transport/failure.js +194 -0
  215. package/dist/transport/group.d.ts +2946 -0
  216. package/dist/transport/group.js +47 -0
  217. package/dist/transport/limits.d.ts +30 -0
  218. package/dist/transport/limits.js +30 -0
  219. package/dist/transport/request.d.ts +9333 -0
  220. package/dist/transport/request.js +121 -0
  221. package/dist/transport/response.d.ts +6247 -0
  222. package/dist/transport/response.js +181 -0
  223. package/dist/transport/runtime.d.ts +77 -0
  224. package/dist/transport/runtime.js +33 -0
  225. package/dist/transport/snapshot.d.ts +978 -0
  226. package/dist/transport/snapshot.js +70 -0
  227. package/dist/tryout/canonical.d.ts +2 -0
  228. package/dist/tryout/canonical.js +11 -0
  229. package/dist/tryout/catalog-hash.d.ts +134 -0
  230. package/dist/tryout/catalog-hash.js +203 -0
  231. package/dist/tryout/catalog.d.ts +376 -0
  232. package/dist/tryout/catalog.js +147 -0
  233. package/dist/tryout/content-hash.d.ts +89 -0
  234. package/dist/tryout/content-hash.js +72 -0
  235. package/dist/tryout/identity.d.ts +12 -0
  236. package/dist/tryout/identity.js +46 -0
  237. package/dist/tryout/key.d.ts +4 -0
  238. package/dist/tryout/key.js +8 -0
  239. package/dist/tryout/language.d.ts +24 -0
  240. package/dist/tryout/language.js +32 -0
  241. package/dist/tryout/locale-closure.d.ts +20 -0
  242. package/dist/tryout/locale-closure.js +164 -0
  243. package/dist/tryout/placement-closure.d.ts +5 -0
  244. package/dist/tryout/placement-closure.js +30 -0
  245. package/dist/tryout/placement-hash.d.ts +11 -0
  246. package/dist/tryout/placement-hash.js +55 -0
  247. package/dist/tryout/placement.d.ts +280 -0
  248. package/dist/tryout/placement.js +82 -0
  249. package/dist/tryout/row-hash.d.ts +28 -0
  250. package/dist/tryout/row-hash.js +50 -0
  251. package/dist/tryout/runtime/canonical.d.ts +8 -0
  252. package/dist/tryout/runtime/canonical.js +33 -0
  253. package/dist/tryout/runtime/hash.d.ts +32 -0
  254. package/dist/tryout/runtime/hash.js +11 -0
  255. package/dist/tryout/runtime/source.d.ts +42 -0
  256. package/dist/tryout/runtime/source.js +47 -0
  257. package/dist/tryout/runtime/spec.d.ts +58 -0
  258. package/dist/tryout/runtime/spec.js +21 -0
  259. package/dist/tryout/runtime/verify.d.ts +61 -0
  260. package/dist/tryout/runtime/verify.js +69 -0
  261. package/dist/tryout/snapshot/canonical.d.ts +7 -0
  262. package/dist/tryout/snapshot/canonical.js +17 -0
  263. package/dist/tryout/snapshot/hash.d.ts +8 -0
  264. package/dist/tryout/snapshot/hash.js +19 -0
  265. package/dist/tryout/snapshot/spec.d.ts +46 -0
  266. package/dist/tryout/snapshot/spec.js +30 -0
  267. package/dist/tryout/spec.d.ts +13 -0
  268. package/dist/tryout/spec.js +15 -0
  269. package/package.json +506 -0
@@ -0,0 +1,100 @@
1
+ import { Match, Schema } from "effect";
2
+ import { AppLocaleCodeSchema, ENGLISH_APP_LOCALE_CODE, GERMAN_APP_LOCALE_CODE, INDONESIAN_APP_LOCALE_CODE, } from "#contracts/locale";
3
+ /** Official source identities whose bytes are pinned inside Aksara. */
4
+ export const QuranEmbeddedSourceIdSchema = Schema.Literals([
5
+ "tanzil-text",
6
+ "tanzil-metadata",
7
+ "kemenag-names",
8
+ "bubenheim-names",
9
+ "quranenc-english",
10
+ "quranenc-indonesian",
11
+ "quranenc-german",
12
+ "quranenc-tafsir",
13
+ ]);
14
+ /** Official source identities that Aksara may link to but not republish. */
15
+ export const QuranExternalSourceIdSchema = Schema.Literals([
16
+ "mokhtasar-english",
17
+ "mokhtasar-german",
18
+ ]);
19
+ /** Exact official Quran source identities in visible attribution order. */
20
+ export const QuranSourceIdSchema = Schema.Literals([
21
+ ...QuranEmbeddedSourceIdSchema.literals,
22
+ ...QuranExternalSourceIdSchema.literals,
23
+ ]);
24
+ /** Canonical order of every official source supported by the contract. */
25
+ export const QURAN_SOURCE_IDS = QuranSourceIdSchema.literals;
26
+ /** Locale-specific translation field in Quran source provenance. */
27
+ export const QuranTranslationProvenanceScopeSchema = Schema.TemplateLiteral([
28
+ AppLocaleCodeSchema,
29
+ "-translation",
30
+ ]);
31
+ /** Locale-specific surah-name field in Quran source provenance. */
32
+ export const QuranNameProvenanceScopeSchema = Schema.TemplateLiteral([
33
+ AppLocaleCodeSchema,
34
+ "-surah-name",
35
+ ]);
36
+ const QURAN_NAME_BY_LOCALE = {
37
+ [ENGLISH_APP_LOCALE_CODE]: {
38
+ scope: "en-surah-name",
39
+ sourceId: "tanzil-metadata",
40
+ },
41
+ [GERMAN_APP_LOCALE_CODE]: {
42
+ scope: "de-surah-name",
43
+ sourceId: "bubenheim-names",
44
+ },
45
+ [INDONESIAN_APP_LOCALE_CODE]: {
46
+ scope: "id-surah-name",
47
+ sourceId: "kemenag-names",
48
+ },
49
+ };
50
+ const QURAN_TRANSLATION_BY_LOCALE = {
51
+ [ENGLISH_APP_LOCALE_CODE]: {
52
+ scope: "en-translation",
53
+ sourceId: "quranenc-english",
54
+ },
55
+ [GERMAN_APP_LOCALE_CODE]: {
56
+ scope: "de-translation",
57
+ sourceId: "quranenc-german",
58
+ },
59
+ [INDONESIAN_APP_LOCALE_CODE]: {
60
+ scope: "id-translation",
61
+ sourceId: "quranenc-indonesian",
62
+ },
63
+ };
64
+ const QURAN_TAFSIR_BY_LOCALE = {
65
+ [ENGLISH_APP_LOCALE_CODE]: { sourceId: "mokhtasar-english" },
66
+ [GERMAN_APP_LOCALE_CODE]: { sourceId: "mokhtasar-german" },
67
+ [INDONESIAN_APP_LOCALE_CODE]: { sourceId: "quranenc-tafsir" },
68
+ };
69
+ /** Resolves the selected surah-name source identity. */
70
+ export function quranNameSourceId(appLocale) {
71
+ return QURAN_NAME_BY_LOCALE[appLocale].sourceId;
72
+ }
73
+ /** Resolves the selected surah-name provenance scope. */
74
+ export function quranNameProvenanceScope(appLocale) {
75
+ return QURAN_NAME_BY_LOCALE[appLocale].scope;
76
+ }
77
+ /** Resolves the selected translation source identity. */
78
+ export function quranTranslationSourceId(appLocale) {
79
+ return QURAN_TRANSLATION_BY_LOCALE[appLocale].sourceId;
80
+ }
81
+ /** Resolves the selected Tafsir source identity. */
82
+ export function quranTafsirSourceId(appLocale) {
83
+ return QURAN_TAFSIR_BY_LOCALE[appLocale].sourceId;
84
+ }
85
+ /** Resolves the selected translation provenance scope. */
86
+ export function quranTranslationProvenanceScope(appLocale) {
87
+ return QURAN_TRANSLATION_BY_LOCALE[appLocale].scope;
88
+ }
89
+ /** Resolves a translation provenance scope through the canonical locale map. */
90
+ export function quranTranslationSourceForScope(scope) {
91
+ return Match.value(scope).pipe(Match.when("en-translation", () => quranTranslationSourceId(ENGLISH_APP_LOCALE_CODE)), Match.when("id-translation", () => quranTranslationSourceId(INDONESIAN_APP_LOCALE_CODE)), Match.when("de-translation", () => quranTranslationSourceId(GERMAN_APP_LOCALE_CODE)), Match.exhaustive);
92
+ }
93
+ /** Resolves a surah-name provenance scope through the canonical locale map. */
94
+ export function quranNameSourceForScope(scope) {
95
+ return Match.value(scope).pipe(Match.when("en-surah-name", () => quranNameSourceId(ENGLISH_APP_LOCALE_CODE)), Match.when("id-surah-name", () => quranNameSourceId(INDONESIAN_APP_LOCALE_CODE)), Match.when("de-surah-name", () => quranNameSourceId(GERMAN_APP_LOCALE_CODE)), Match.exhaustive);
96
+ }
97
+ /** Selects the signed Arabic and localized translation reading sources. */
98
+ export function quranReadingSourceIds(appLocale) {
99
+ return ["tanzil-text", quranTranslationSourceId(appLocale)];
100
+ }
@@ -0,0 +1,56 @@
1
+ import { Effect, Schema } from "effect";
2
+ /** Semantic translation text and its exact source-authored notes. */
3
+ export declare const QuranTranslationDocumentSchema: Schema.Struct<{
4
+ readonly notes: Schema.$Array<Schema.Struct<{
5
+ readonly number: Schema.Int;
6
+ readonly referenceOffset: Schema.Int;
7
+ readonly text: Schema.String;
8
+ }>>;
9
+ readonly segments: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
10
+ readonly kind: Schema.Literal<"text">;
11
+ readonly offset: Schema.Int;
12
+ readonly value: Schema.String;
13
+ }>, Schema.Struct<{
14
+ readonly kind: Schema.Literal<"note">;
15
+ readonly number: Schema.Int;
16
+ readonly offset: Schema.Int;
17
+ }>]>>;
18
+ }>;
19
+ export type QuranTranslationDocument = typeof QuranTranslationDocumentSchema.Type;
20
+ declare const QuranTranslationNotesError_base: Schema.Class<QuranTranslationNotesError, Schema.TaggedStruct<"QuranTranslationNotesError", {
21
+ readonly reason: Schema.Literals<readonly ["empty-note", "invalid-marker", "invalid-source", "mismatched-markers"]>;
22
+ }>, import("effect/Cause").YieldableError>;
23
+ /** The translation and note markers do not form one exact projection. */
24
+ export declare class QuranTranslationNotesError extends QuranTranslationNotesError_base {
25
+ }
26
+ declare const QuranTranslationSourceSchema: Schema.Struct<{
27
+ readonly footnotes: Schema.String;
28
+ readonly text: Schema.String;
29
+ }>;
30
+ type QuranTranslationSource = typeof QuranTranslationSourceSchema.Type;
31
+ /** Checks that every source marker resolves to one exact non-empty note. */
32
+ export declare function hasConsistentQuranTranslationNotes(source: QuranTranslationSource): boolean;
33
+ /** One verbatim QuranEnc translation with a consistent note relationship. */
34
+ export declare const QuranTranslationSchema: Schema.Struct<{
35
+ readonly footnotes: Schema.String;
36
+ readonly text: Schema.String;
37
+ }>;
38
+ export type QuranTranslation = typeof QuranTranslationSchema.Type;
39
+ /** Parses one exact source translation into linked reference-ready semantics. */
40
+ export declare const parseQuranTranslation: (input: unknown) => Effect.Effect<{
41
+ readonly notes: readonly {
42
+ readonly number: number;
43
+ readonly referenceOffset: number;
44
+ readonly text: string;
45
+ }[];
46
+ readonly segments: readonly ({
47
+ readonly kind: "text";
48
+ readonly offset: number;
49
+ readonly value: string;
50
+ } | {
51
+ readonly kind: "note";
52
+ readonly number: number;
53
+ readonly offset: number;
54
+ })[];
55
+ }, QuranTranslationNotesError, never>;
56
+ export {};
@@ -0,0 +1,142 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { QuranMeaningfulTextSchema } from "#contracts/quran/text";
3
+ const QuranTranslationNoteNumberSchema = Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0)));
4
+ const QuranTranslationOffsetSchema = Schema.Int.pipe(Schema.check(Schema.isGreaterThanOrEqualTo(0)));
5
+ const QuranTranslationSegmentSchema = Schema.Union([
6
+ Schema.Struct({
7
+ kind: Schema.Literal("text"),
8
+ offset: QuranTranslationOffsetSchema,
9
+ value: Schema.String,
10
+ }),
11
+ Schema.Struct({
12
+ kind: Schema.Literal("note"),
13
+ number: QuranTranslationNoteNumberSchema,
14
+ offset: QuranTranslationOffsetSchema,
15
+ }),
16
+ ]);
17
+ const QuranTranslationNoteSchema = Schema.Struct({
18
+ number: QuranTranslationNoteNumberSchema,
19
+ referenceOffset: QuranTranslationOffsetSchema,
20
+ text: Schema.String,
21
+ });
22
+ /** Semantic translation text and its exact source-authored notes. */
23
+ export const QuranTranslationDocumentSchema = Schema.Struct({
24
+ notes: Schema.Array(QuranTranslationNoteSchema),
25
+ segments: Schema.Array(QuranTranslationSegmentSchema),
26
+ });
27
+ /** The translation and note markers do not form one exact projection. */
28
+ export class QuranTranslationNotesError extends Schema.TaggedError()("QuranTranslationNotesError", {
29
+ reason: Schema.Literals([
30
+ "empty-note",
31
+ "invalid-marker",
32
+ "invalid-source",
33
+ "mismatched-markers",
34
+ ]),
35
+ }) {
36
+ }
37
+ const QuranTranslationSourceSchema = Schema.Struct({
38
+ footnotes: Schema.String,
39
+ text: QuranMeaningfulTextSchema,
40
+ });
41
+ /** Reads every numeric marker without treating editorial brackets as notes. */
42
+ function readMarkers(source) {
43
+ const markers = [];
44
+ for (const match of source.matchAll(/\[(\d+)\]/gu)) {
45
+ const rawNumber = match[0].slice(1, -1);
46
+ const start = match.index;
47
+ const number = Number(rawNumber);
48
+ if (rawNumber !== String(number) ||
49
+ !Schema.is(QuranTranslationNoteNumberSchema)(number)) {
50
+ return { _tag: "Failure" };
51
+ }
52
+ markers.push({ end: start + match[0].length, number, start });
53
+ }
54
+ return { _tag: "Success", markers };
55
+ }
56
+ /** Converts the translation body to text and note-reference segments. */
57
+ function segmentTranslation(source, markers) {
58
+ const segments = [];
59
+ let start = 0;
60
+ for (const marker of markers) {
61
+ if (marker.start > start) {
62
+ segments.push({
63
+ kind: "text",
64
+ offset: start,
65
+ value: source.slice(start, marker.start),
66
+ });
67
+ }
68
+ segments.push({
69
+ kind: "note",
70
+ number: marker.number,
71
+ offset: marker.start,
72
+ });
73
+ start = marker.end;
74
+ }
75
+ if (start < source.length || segments.length === 0) {
76
+ segments.push({ kind: "text", offset: start, value: source.slice(start) });
77
+ }
78
+ return segments;
79
+ }
80
+ /** Analyzes one source translation through the canonical note grammar. */
81
+ function analyzeTranslation(source) {
82
+ const referencesResult = readMarkers(source.text);
83
+ const definitionsResult = readMarkers(source.footnotes);
84
+ if (referencesResult._tag === "Failure" ||
85
+ definitionsResult._tag === "Failure") {
86
+ return { _tag: "Failure", reason: "invalid-marker" };
87
+ }
88
+ const references = referencesResult.markers;
89
+ const definitions = definitionsResult.markers;
90
+ const uniqueReferences = references.filter((reference, index) => references.findIndex(({ number }) => number === reference.number) ===
91
+ index);
92
+ const noteCandidates = definitions.map((definition, index) => ({
93
+ definition,
94
+ referenceOffset: uniqueReferences[index]?.start ?? -1,
95
+ }));
96
+ const definitionNumbers = definitions.map(({ number }) => number);
97
+ const hasDuplicateDefinition = definitionNumbers.some((number, index) => definitionNumbers.indexOf(number) !== index);
98
+ const hasMismatchedMarkers = hasDuplicateDefinition ||
99
+ uniqueReferences.length !== definitionNumbers.length ||
100
+ noteCandidates.some(({ definition, referenceOffset }, index) => referenceOffset < 0 ||
101
+ definition.number !== uniqueReferences[index]?.number) ||
102
+ (definitions[0] === undefined
103
+ ? source.footnotes.trim().length > 0
104
+ : source.footnotes.slice(0, definitions[0].start).trim().length > 0);
105
+ if (hasMismatchedMarkers) {
106
+ return { _tag: "Failure", reason: "mismatched-markers" };
107
+ }
108
+ const notes = noteCandidates.map(({ definition, referenceOffset }, index) => ({
109
+ number: definition.number,
110
+ referenceOffset,
111
+ text: source.footnotes
112
+ .slice(definition.end, definitions[index + 1]?.start)
113
+ .trim(),
114
+ }));
115
+ if (notes.some(({ text }) => text.length === 0)) {
116
+ return { _tag: "Failure", reason: "empty-note" };
117
+ }
118
+ return {
119
+ _tag: "Success",
120
+ document: QuranTranslationDocumentSchema.make({
121
+ notes,
122
+ segments: segmentTranslation(source.text, references),
123
+ }),
124
+ };
125
+ }
126
+ /** Checks that every source marker resolves to one exact non-empty note. */
127
+ export function hasConsistentQuranTranslationNotes(source) {
128
+ return analyzeTranslation(source)._tag === "Success";
129
+ }
130
+ /** One verbatim QuranEnc translation with a consistent note relationship. */
131
+ export const QuranTranslationSchema = QuranTranslationSourceSchema.pipe(Schema.check(Schema.makeFilter(hasConsistentQuranTranslationNotes, {
132
+ message: "Quran translation markers must resolve to exact non-empty source notes.",
133
+ })));
134
+ /** Parses one exact source translation into linked reference-ready semantics. */
135
+ export const parseQuranTranslation = Effect.fn("AksaraContracts.parseQuranTranslation")(function* (input) {
136
+ const source = yield* Schema.decodeUnknownEffect(QuranTranslationSourceSchema)(input, { onExcessProperty: "error" }).pipe(Effect.mapError(() => new QuranTranslationNotesError({ reason: "invalid-source" })));
137
+ const result = analyzeTranslation(source);
138
+ if (result._tag === "Failure") {
139
+ return yield* new QuranTranslationNotesError({ reason: result.reason });
140
+ }
141
+ return result.document;
142
+ });
@@ -0,0 +1,257 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { type ActiveAppLocaleList } from "#contracts/locale";
3
+ import { type QuranSourceId } from "#contracts/quran/identity";
4
+ /** Complete source-field vocabulary supported by current Quran publication. */
5
+ export declare const QuranProvenanceScopeSchema: Schema.Union<readonly [Schema.Union<readonly [Schema.Literals<readonly ["arabic-text", "metadata"]>, Schema.Literals<readonly ["en-tafsir-access", "de-tafsir-access"]>, Schema.Literal<"id-tafsir">]>, Schema.TemplateLiteral<readonly [Schema.Literals<readonly ["en", "id", "de"]>, "-surah-name"]>, Schema.TemplateLiteral<readonly [Schema.Literals<readonly ["en", "id", "de"]>, "-translation"]>]>;
6
+ export type QuranProvenanceScope = typeof QuranProvenanceScopeSchema.Type;
7
+ /** Derives the exact provenance scope order for one active locale set. */
8
+ export declare function quranProvenanceScopes(activeAppLocales: ActiveAppLocaleList): readonly QuranProvenanceScope[];
9
+ /** Resolves the only official source allowed to prove one provenance scope. */
10
+ export declare function quranSourceForProvenanceScope(scope: QuranProvenanceScope): QuranSourceId;
11
+ /** One reviewed official artifact and its field-level permission decision. */
12
+ export declare const QuranProvenanceRecordSchema: Schema.Struct<{
13
+ readonly attribution: Schema.Union<readonly [Schema.Struct<{
14
+ readonly copy: Schema.NonEmptyArray<Schema.Struct<{
15
+ readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
16
+ readonly notice: Schema.Trimmed;
17
+ readonly title: Schema.Trimmed;
18
+ }>>;
19
+ readonly publisher: Schema.Trimmed;
20
+ readonly retrievedAt: Schema.String;
21
+ readonly sourceUrl: Schema.String;
22
+ readonly updateUrl: Schema.String;
23
+ readonly version: Schema.Trimmed;
24
+ readonly artifact: Schema.Struct<{
25
+ readonly byteCount: Schema.Int;
26
+ readonly digest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
27
+ readonly fileCount: Schema.Int;
28
+ }>;
29
+ readonly id: Schema.Literals<readonly ["tanzil-text", "tanzil-metadata", "kemenag-names", "bubenheim-names", "quranenc-english", "quranenc-indonesian", "quranenc-german", "quranenc-tafsir"]>;
30
+ readonly kind: Schema.Literal<"embedded">;
31
+ readonly terms: Schema.Struct<{
32
+ readonly artifact: Schema.Struct<{
33
+ readonly byteCount: Schema.Int;
34
+ readonly digest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
35
+ readonly fileCount: Schema.Int;
36
+ }>;
37
+ readonly url: Schema.String;
38
+ }>;
39
+ }>, Schema.Struct<{
40
+ readonly copy: Schema.NonEmptyArray<Schema.Struct<{
41
+ readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
42
+ readonly notice: Schema.Trimmed;
43
+ readonly title: Schema.Trimmed;
44
+ }>>;
45
+ readonly publisher: Schema.Trimmed;
46
+ readonly retrievedAt: Schema.String;
47
+ readonly sourceUrl: Schema.String;
48
+ readonly updateUrl: Schema.String;
49
+ readonly version: Schema.Trimmed;
50
+ readonly id: Schema.Literals<readonly ["mokhtasar-english", "mokhtasar-german"]>;
51
+ readonly kind: Schema.Literal<"external">;
52
+ readonly terms: Schema.Struct<{
53
+ readonly access: Schema.Literal<"link-only">;
54
+ readonly url: Schema.String;
55
+ }>;
56
+ }>]>;
57
+ readonly evidence: Schema.Trimmed;
58
+ readonly scope: Schema.Union<readonly [Schema.Union<readonly [Schema.Literals<readonly ["arabic-text", "metadata"]>, Schema.Literals<readonly ["en-tafsir-access", "de-tafsir-access"]>, Schema.Literal<"id-tafsir">]>, Schema.TemplateLiteral<readonly [Schema.Literals<readonly ["en", "id", "de"]>, "-surah-name"]>, Schema.TemplateLiteral<readonly [Schema.Literals<readonly ["en", "id", "de"]>, "-translation"]>]>;
59
+ readonly status: Schema.Literals<readonly ["approved", "blocked"]>;
60
+ }>;
61
+ export type QuranProvenanceRecord = typeof QuranProvenanceRecordSchema.Type;
62
+ /** Complete ordered evidence set that gates Quran production publication. */
63
+ export declare const QuranProvenanceManifestSchema: Schema.Struct<{
64
+ readonly activeAppLocales: Schema.NonEmptyArray<Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">>;
65
+ readonly digest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
66
+ readonly records: Schema.NonEmptyArray<Schema.Struct<{
67
+ readonly attribution: Schema.Union<readonly [Schema.Struct<{
68
+ readonly copy: Schema.NonEmptyArray<Schema.Struct<{
69
+ readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
70
+ readonly notice: Schema.Trimmed;
71
+ readonly title: Schema.Trimmed;
72
+ }>>;
73
+ readonly publisher: Schema.Trimmed;
74
+ readonly retrievedAt: Schema.String;
75
+ readonly sourceUrl: Schema.String;
76
+ readonly updateUrl: Schema.String;
77
+ readonly version: Schema.Trimmed;
78
+ readonly artifact: Schema.Struct<{
79
+ readonly byteCount: Schema.Int;
80
+ readonly digest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
81
+ readonly fileCount: Schema.Int;
82
+ }>;
83
+ readonly id: Schema.Literals<readonly ["tanzil-text", "tanzil-metadata", "kemenag-names", "bubenheim-names", "quranenc-english", "quranenc-indonesian", "quranenc-german", "quranenc-tafsir"]>;
84
+ readonly kind: Schema.Literal<"embedded">;
85
+ readonly terms: Schema.Struct<{
86
+ readonly artifact: Schema.Struct<{
87
+ readonly byteCount: Schema.Int;
88
+ readonly digest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
89
+ readonly fileCount: Schema.Int;
90
+ }>;
91
+ readonly url: Schema.String;
92
+ }>;
93
+ }>, Schema.Struct<{
94
+ readonly copy: Schema.NonEmptyArray<Schema.Struct<{
95
+ readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
96
+ readonly notice: Schema.Trimmed;
97
+ readonly title: Schema.Trimmed;
98
+ }>>;
99
+ readonly publisher: Schema.Trimmed;
100
+ readonly retrievedAt: Schema.String;
101
+ readonly sourceUrl: Schema.String;
102
+ readonly updateUrl: Schema.String;
103
+ readonly version: Schema.Trimmed;
104
+ readonly id: Schema.Literals<readonly ["mokhtasar-english", "mokhtasar-german"]>;
105
+ readonly kind: Schema.Literal<"external">;
106
+ readonly terms: Schema.Struct<{
107
+ readonly access: Schema.Literal<"link-only">;
108
+ readonly url: Schema.String;
109
+ }>;
110
+ }>]>;
111
+ readonly evidence: Schema.Trimmed;
112
+ readonly scope: Schema.Union<readonly [Schema.Union<readonly [Schema.Literals<readonly ["arabic-text", "metadata"]>, Schema.Literals<readonly ["en-tafsir-access", "de-tafsir-access"]>, Schema.Literal<"id-tafsir">]>, Schema.TemplateLiteral<readonly [Schema.Literals<readonly ["en", "id", "de"]>, "-surah-name"]>, Schema.TemplateLiteral<readonly [Schema.Literals<readonly ["en", "id", "de"]>, "-translation"]>]>;
113
+ readonly status: Schema.Literals<readonly ["approved", "blocked"]>;
114
+ }>>;
115
+ readonly status: Schema.Literals<readonly ["approved", "blocked"]>;
116
+ }>;
117
+ export type QuranProvenanceManifest = typeof QuranProvenanceManifestSchema.Type;
118
+ declare const QuranProvenanceCoverageError_base: Schema.Class<QuranProvenanceCoverageError, Schema.TaggedStruct<"QuranProvenanceCoverageError", {
119
+ readonly actualScopes: Schema.$Array<Schema.Union<readonly [Schema.Union<readonly [Schema.Literals<readonly ["arabic-text", "metadata"]>, Schema.Literals<readonly ["en-tafsir-access", "de-tafsir-access"]>, Schema.Literal<"id-tafsir">]>, Schema.TemplateLiteral<readonly [Schema.Literals<readonly ["en", "id", "de"]>, "-surah-name"]>, Schema.TemplateLiteral<readonly [Schema.Literals<readonly ["en", "id", "de"]>, "-translation"]>]>>;
120
+ }>, import("effect/Cause").YieldableError>;
121
+ /** Quran provenance omitted or misordered an active-locale scope. */
122
+ export declare class QuranProvenanceCoverageError extends QuranProvenanceCoverageError_base {
123
+ }
124
+ declare const QuranProvenanceHashError_base: Schema.Class<QuranProvenanceHashError, Schema.TaggedStruct<"QuranProvenanceHashError", {}>, import("effect/Cause").YieldableError>;
125
+ /** Node could not compute the deterministic provenance digest. */
126
+ export declare class QuranProvenanceHashError extends QuranProvenanceHashError_base {
127
+ }
128
+ /** Produces stable JSON for one reviewed Quran provenance record. */
129
+ export declare function canonicalizeQuranProvenance(record: QuranProvenanceRecord): string;
130
+ /** Digests exact ordered provenance records under their active locale set. */
131
+ export declare const hashQuranProvenance: (input: {
132
+ readonly activeAppLocales: ActiveAppLocaleList;
133
+ readonly records: readonly QuranProvenanceRecord[];
134
+ }) => Effect.Effect<string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">, QuranProvenanceHashError, never>;
135
+ /** Builds a snapshot provenance gate from exact reviewed source records. */
136
+ export declare const makeQuranProvenanceManifest: (input: {
137
+ readonly activeAppLocales: ActiveAppLocaleList;
138
+ readonly records: readonly QuranProvenanceRecord[];
139
+ }) => Effect.Effect<{
140
+ readonly activeAppLocales: readonly [("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraAppLocale">, ...(("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraAppLocale">)[]];
141
+ readonly digest: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
142
+ readonly records: readonly [{
143
+ readonly attribution: {
144
+ readonly copy: readonly [{
145
+ readonly appLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraAppLocale">;
146
+ readonly notice: string;
147
+ readonly title: string;
148
+ }, ...{
149
+ readonly appLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraAppLocale">;
150
+ readonly notice: string;
151
+ readonly title: string;
152
+ }[]];
153
+ readonly publisher: string;
154
+ readonly retrievedAt: string;
155
+ readonly sourceUrl: string;
156
+ readonly updateUrl: string;
157
+ readonly version: string;
158
+ readonly artifact: {
159
+ readonly byteCount: number;
160
+ readonly digest: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
161
+ readonly fileCount: number;
162
+ };
163
+ readonly id: "bubenheim-names" | "kemenag-names" | "quranenc-english" | "quranenc-german" | "quranenc-indonesian" | "quranenc-tafsir" | "tanzil-metadata" | "tanzil-text";
164
+ readonly kind: "embedded";
165
+ readonly terms: {
166
+ readonly artifact: {
167
+ readonly byteCount: number;
168
+ readonly digest: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
169
+ readonly fileCount: number;
170
+ };
171
+ readonly url: string;
172
+ };
173
+ } | {
174
+ readonly copy: readonly [{
175
+ readonly appLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraAppLocale">;
176
+ readonly notice: string;
177
+ readonly title: string;
178
+ }, ...{
179
+ readonly appLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraAppLocale">;
180
+ readonly notice: string;
181
+ readonly title: string;
182
+ }[]];
183
+ readonly publisher: string;
184
+ readonly retrievedAt: string;
185
+ readonly sourceUrl: string;
186
+ readonly updateUrl: string;
187
+ readonly version: string;
188
+ readonly id: "mokhtasar-english" | "mokhtasar-german";
189
+ readonly kind: "external";
190
+ readonly terms: {
191
+ readonly access: "link-only";
192
+ readonly url: string;
193
+ };
194
+ };
195
+ readonly evidence: string;
196
+ readonly scope: "arabic-text" | "de-surah-name" | "de-tafsir-access" | "de-translation" | "en-surah-name" | "en-tafsir-access" | "en-translation" | "id-surah-name" | "id-tafsir" | "id-translation" | "metadata";
197
+ readonly status: "approved" | "blocked";
198
+ }, ...{
199
+ readonly attribution: {
200
+ readonly copy: readonly [{
201
+ readonly appLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraAppLocale">;
202
+ readonly notice: string;
203
+ readonly title: string;
204
+ }, ...{
205
+ readonly appLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraAppLocale">;
206
+ readonly notice: string;
207
+ readonly title: string;
208
+ }[]];
209
+ readonly publisher: string;
210
+ readonly retrievedAt: string;
211
+ readonly sourceUrl: string;
212
+ readonly updateUrl: string;
213
+ readonly version: string;
214
+ readonly artifact: {
215
+ readonly byteCount: number;
216
+ readonly digest: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
217
+ readonly fileCount: number;
218
+ };
219
+ readonly id: "bubenheim-names" | "kemenag-names" | "quranenc-english" | "quranenc-german" | "quranenc-indonesian" | "quranenc-tafsir" | "tanzil-metadata" | "tanzil-text";
220
+ readonly kind: "embedded";
221
+ readonly terms: {
222
+ readonly artifact: {
223
+ readonly byteCount: number;
224
+ readonly digest: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
225
+ readonly fileCount: number;
226
+ };
227
+ readonly url: string;
228
+ };
229
+ } | {
230
+ readonly copy: readonly [{
231
+ readonly appLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraAppLocale">;
232
+ readonly notice: string;
233
+ readonly title: string;
234
+ }, ...{
235
+ readonly appLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraAppLocale">;
236
+ readonly notice: string;
237
+ readonly title: string;
238
+ }[]];
239
+ readonly publisher: string;
240
+ readonly retrievedAt: string;
241
+ readonly sourceUrl: string;
242
+ readonly updateUrl: string;
243
+ readonly version: string;
244
+ readonly id: "mokhtasar-english" | "mokhtasar-german";
245
+ readonly kind: "external";
246
+ readonly terms: {
247
+ readonly access: "link-only";
248
+ readonly url: string;
249
+ };
250
+ };
251
+ readonly evidence: string;
252
+ readonly scope: "arabic-text" | "de-surah-name" | "de-tafsir-access" | "de-translation" | "en-surah-name" | "en-tafsir-access" | "en-translation" | "id-surah-name" | "id-tafsir" | "id-translation" | "metadata";
253
+ readonly status: "approved" | "blocked";
254
+ }[]];
255
+ readonly status: "approved" | "blocked";
256
+ }, QuranProvenanceCoverageError | QuranProvenanceHashError, never>;
257
+ export {};