@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.
- package/LICENSE +185 -0
- package/README.md +73 -0
- package/dist/artifact/integrity.d.ts +29 -0
- package/dist/artifact/integrity.js +54 -0
- package/dist/artifact/limits.d.ts +26 -0
- package/dist/artifact/limits.js +46 -0
- package/dist/artifact/source.d.ts +21 -0
- package/dist/artifact/source.js +24 -0
- package/dist/artifact/spec.d.ts +148 -0
- package/dist/artifact/spec.js +92 -0
- package/dist/artifact/verify.d.ts +26 -0
- package/dist/artifact/verify.js +18 -0
- package/dist/cache/content.d.ts +52 -0
- package/dist/cache/content.js +80 -0
- package/dist/content.d.ts +168 -0
- package/dist/content.js +107 -0
- package/dist/country.d.ts +4 -0
- package/dist/country.js +8 -0
- package/dist/date.d.ts +24 -0
- package/dist/date.js +44 -0
- package/dist/decode.d.ts +4 -0
- package/dist/decode.js +8 -0
- package/dist/delivery.d.ts +4 -0
- package/dist/delivery.js +7 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +8 -0
- package/dist/graph/family.d.ts +45 -0
- package/dist/graph/family.js +85 -0
- package/dist/graph/identity.d.ts +19 -0
- package/dist/graph/identity.js +39 -0
- package/dist/graph/spec.d.ts +20 -0
- package/dist/graph/spec.js +26 -0
- package/dist/hash/text.d.ts +10 -0
- package/dist/hash/text.js +20 -0
- package/dist/ids.d.ts +27 -0
- package/dist/ids.js +63 -0
- package/dist/limits.d.ts +10 -0
- package/dist/limits.js +10 -0
- package/dist/locale.d.ts +37 -0
- package/dist/locale.js +53 -0
- package/dist/material/domain.d.ts +4 -0
- package/dist/material/domain.js +8 -0
- package/dist/preview/artifact.d.ts +198 -0
- package/dist/preview/artifact.js +20 -0
- package/dist/preview/auth.d.ts +71 -0
- package/dist/preview/auth.js +49 -0
- package/dist/preview/document.d.ts +692 -0
- package/dist/preview/document.js +90 -0
- package/dist/preview/spec.d.ts +2517 -0
- package/dist/preview/spec.js +142 -0
- package/dist/preview/target.d.ts +172 -0
- package/dist/preview/target.js +70 -0
- package/dist/program/curriculum.d.ts +69 -0
- package/dist/program/curriculum.js +181 -0
- package/dist/program/snapshot/digest.d.ts +26 -0
- package/dist/program/snapshot/digest.js +220 -0
- package/dist/program/snapshot/hash.d.ts +31 -0
- package/dist/program/snapshot/hash.js +40 -0
- package/dist/program/snapshot/row-hash.d.ts +155 -0
- package/dist/program/snapshot/row-hash.js +34 -0
- package/dist/program/snapshot/row.d.ts +139 -0
- package/dist/program/snapshot/row.js +28 -0
- package/dist/program/snapshot/spec.d.ts +36 -0
- package/dist/program/snapshot/spec.js +39 -0
- package/dist/program/spec.d.ts +85 -0
- package/dist/program/spec.js +197 -0
- package/dist/projection/article.d.ts +145 -0
- package/dist/projection/article.js +150 -0
- package/dist/projection/digest.d.ts +261 -0
- package/dist/projection/digest.js +59 -0
- package/dist/projection/hash.d.ts +3 -0
- package/dist/projection/hash.js +10 -0
- package/dist/projection/material.d.ts +109 -0
- package/dist/projection/material.js +160 -0
- package/dist/projection/page.d.ts +112 -0
- package/dist/projection/page.js +106 -0
- package/dist/projection/question.d.ts +520 -0
- package/dist/projection/question.js +109 -0
- package/dist/projection/spec.d.ts +503 -0
- package/dist/projection/spec.js +56 -0
- package/dist/projection/verify.d.ts +281 -0
- package/dist/projection/verify.js +86 -0
- package/dist/question/identity.d.ts +175 -0
- package/dist/question/identity.js +205 -0
- package/dist/question/item.d.ts +453 -0
- package/dist/question/item.js +146 -0
- package/dist/question/response.d.ts +175 -0
- package/dist/question/response.js +150 -0
- package/dist/quran/attribution.d.ts +48 -0
- package/dist/quran/attribution.js +44 -0
- package/dist/quran/identity.d.ts +105 -0
- package/dist/quran/identity.js +100 -0
- package/dist/quran/notes.d.ts +56 -0
- package/dist/quran/notes.js +142 -0
- package/dist/quran/provenance.d.ts +257 -0
- package/dist/quran/provenance.js +144 -0
- package/dist/quran/snapshot/digest.d.ts +33 -0
- package/dist/quran/snapshot/digest.js +232 -0
- package/dist/quran/snapshot/hash.d.ts +51 -0
- package/dist/quran/snapshot/hash.js +50 -0
- package/dist/quran/snapshot/row/hash.d.ts +748 -0
- package/dist/quran/snapshot/row/hash.js +115 -0
- package/dist/quran/snapshot/row.d.ts +354 -0
- package/dist/quran/snapshot/row.js +91 -0
- package/dist/quran/snapshot/spec.d.ts +50 -0
- package/dist/quran/snapshot/spec.js +66 -0
- package/dist/quran/source.d.ts +206 -0
- package/dist/quran/source.js +153 -0
- package/dist/quran/spec.d.ts +47 -0
- package/dist/quran/spec.js +41 -0
- package/dist/quran/text.d.ts +7 -0
- package/dist/quran/text.js +11 -0
- package/dist/release/canonical.d.ts +23 -0
- package/dist/release/canonical.js +29 -0
- package/dist/release/current/evidence.d.ts +424 -0
- package/dist/release/current/evidence.js +41 -0
- package/dist/release/current/runtime.d.ts +4 -0
- package/dist/release/current/runtime.js +15 -0
- package/dist/release/current/state.d.ts +567 -0
- package/dist/release/current/state.js +91 -0
- package/dist/release/digest.d.ts +54 -0
- package/dist/release/digest.js +71 -0
- package/dist/release/hash.d.ts +72 -0
- package/dist/release/hash.js +14 -0
- package/dist/release/head.d.ts +206 -0
- package/dist/release/head.js +131 -0
- package/dist/release/items.d.ts +98 -0
- package/dist/release/items.js +114 -0
- package/dist/release/lifecycle.d.ts +297 -0
- package/dist/release/lifecycle.js +97 -0
- package/dist/release/origin.d.ts +30 -0
- package/dist/release/origin.js +24 -0
- package/dist/release/policy.d.ts +45 -0
- package/dist/release/policy.js +124 -0
- package/dist/release/result/digest.d.ts +127 -0
- package/dist/release/result/digest.js +140 -0
- package/dist/release/result/spec.d.ts +4 -0
- package/dist/release/result/spec.js +5 -0
- package/dist/release/rollback/digest.d.ts +126 -0
- package/dist/release/rollback/digest.js +92 -0
- package/dist/release/rollback/spec.d.ts +1729 -0
- package/dist/release/rollback/spec.js +156 -0
- package/dist/release/route/digest.d.ts +45 -0
- package/dist/release/route/digest.js +59 -0
- package/dist/release/route/page.d.ts +56 -0
- package/dist/release/route/page.js +46 -0
- package/dist/release/route/spec.d.ts +49 -0
- package/dist/release/route/spec.js +40 -0
- package/dist/release/route/verify.d.ts +66 -0
- package/dist/release/route/verify.js +67 -0
- package/dist/release/signing.d.ts +6 -0
- package/dist/release/signing.js +38 -0
- package/dist/release/snapshot/data.d.ts +475 -0
- package/dist/release/snapshot/data.js +74 -0
- package/dist/release/snapshot/evidence-requirement.d.ts +22 -0
- package/dist/release/snapshot/evidence-requirement.js +21 -0
- package/dist/release/snapshot/evidence.d.ts +58 -0
- package/dist/release/snapshot/evidence.js +14 -0
- package/dist/release/snapshot/program-evidence.d.ts +17 -0
- package/dist/release/snapshot/program-evidence.js +39 -0
- package/dist/release/snapshot/quran-evidence.d.ts +27 -0
- package/dist/release/snapshot/quran-evidence.js +43 -0
- package/dist/release/snapshot/scope.d.ts +60 -0
- package/dist/release/snapshot/scope.js +102 -0
- package/dist/release/snapshot/spec.d.ts +193 -0
- package/dist/release/snapshot/spec.js +139 -0
- package/dist/release/snapshot/tryout-evidence.d.ts +22 -0
- package/dist/release/snapshot/tryout-evidence.js +86 -0
- package/dist/release/snapshot/verify.d.ts +710 -0
- package/dist/release/snapshot/verify.js +147 -0
- package/dist/release/spec.d.ts +491 -0
- package/dist/release/spec.js +200 -0
- package/dist/release/verify.d.ts +98 -0
- package/dist/release/verify.js +70 -0
- package/dist/renderer/compatibility.d.ts +35 -0
- package/dist/renderer/compatibility.js +48 -0
- package/dist/renderer/component.d.ts +99 -0
- package/dist/renderer/component.js +102 -0
- package/dist/renderer/contract.d.ts +144 -0
- package/dist/renderer/contract.js +122 -0
- package/dist/renderer/domain.d.ts +6 -0
- package/dist/renderer/domain.js +18 -0
- package/dist/renderer/manifest.d.ts +86 -0
- package/dist/renderer/manifest.js +49 -0
- package/dist/renderer/selection.d.ts +39 -0
- package/dist/renderer/selection.js +87 -0
- package/dist/runtime/error.d.ts +8 -0
- package/dist/runtime/error.js +20 -0
- package/dist/runtime/protected/limits.d.ts +10 -0
- package/dist/runtime/protected/limits.js +15 -0
- package/dist/runtime/protected/spec.d.ts +328 -0
- package/dist/runtime/protected/spec.js +79 -0
- package/dist/runtime/protected/verify.d.ts +97 -0
- package/dist/runtime/protected/verify.js +72 -0
- package/dist/runtime/result.d.ts +12 -0
- package/dist/runtime/result.js +17 -0
- package/dist/runtime/spec.d.ts +705 -0
- package/dist/runtime/spec.js +61 -0
- package/dist/runtime/verify.d.ts +479 -0
- package/dist/runtime/verify.js +123 -0
- package/dist/signature/spec.d.ts +53 -0
- package/dist/signature/spec.js +29 -0
- package/dist/signature/trusted.d.ts +19 -0
- package/dist/signature/trusted.js +32 -0
- package/dist/signature/verify.d.ts +10 -0
- package/dist/signature/verify.js +82 -0
- package/dist/text/order.d.ts +2 -0
- package/dist/text/order.js +10 -0
- package/dist/text/syntax.d.ts +6 -0
- package/dist/text/syntax.js +15 -0
- package/dist/transport/batch.d.ts +971 -0
- package/dist/transport/batch.js +101 -0
- package/dist/transport/failure.d.ts +168 -0
- package/dist/transport/failure.js +194 -0
- package/dist/transport/group.d.ts +2946 -0
- package/dist/transport/group.js +47 -0
- package/dist/transport/limits.d.ts +30 -0
- package/dist/transport/limits.js +30 -0
- package/dist/transport/request.d.ts +9333 -0
- package/dist/transport/request.js +121 -0
- package/dist/transport/response.d.ts +6247 -0
- package/dist/transport/response.js +181 -0
- package/dist/transport/runtime.d.ts +77 -0
- package/dist/transport/runtime.js +33 -0
- package/dist/transport/snapshot.d.ts +978 -0
- package/dist/transport/snapshot.js +70 -0
- package/dist/tryout/canonical.d.ts +2 -0
- package/dist/tryout/canonical.js +11 -0
- package/dist/tryout/catalog-hash.d.ts +134 -0
- package/dist/tryout/catalog-hash.js +203 -0
- package/dist/tryout/catalog.d.ts +376 -0
- package/dist/tryout/catalog.js +147 -0
- package/dist/tryout/content-hash.d.ts +89 -0
- package/dist/tryout/content-hash.js +72 -0
- package/dist/tryout/identity.d.ts +12 -0
- package/dist/tryout/identity.js +46 -0
- package/dist/tryout/key.d.ts +4 -0
- package/dist/tryout/key.js +8 -0
- package/dist/tryout/language.d.ts +24 -0
- package/dist/tryout/language.js +32 -0
- package/dist/tryout/locale-closure.d.ts +20 -0
- package/dist/tryout/locale-closure.js +164 -0
- package/dist/tryout/placement-closure.d.ts +5 -0
- package/dist/tryout/placement-closure.js +30 -0
- package/dist/tryout/placement-hash.d.ts +11 -0
- package/dist/tryout/placement-hash.js +55 -0
- package/dist/tryout/placement.d.ts +280 -0
- package/dist/tryout/placement.js +82 -0
- package/dist/tryout/row-hash.d.ts +28 -0
- package/dist/tryout/row-hash.js +50 -0
- package/dist/tryout/runtime/canonical.d.ts +8 -0
- package/dist/tryout/runtime/canonical.js +33 -0
- package/dist/tryout/runtime/hash.d.ts +32 -0
- package/dist/tryout/runtime/hash.js +11 -0
- package/dist/tryout/runtime/source.d.ts +42 -0
- package/dist/tryout/runtime/source.js +47 -0
- package/dist/tryout/runtime/spec.d.ts +58 -0
- package/dist/tryout/runtime/spec.js +21 -0
- package/dist/tryout/runtime/verify.d.ts +61 -0
- package/dist/tryout/runtime/verify.js +69 -0
- package/dist/tryout/snapshot/canonical.d.ts +7 -0
- package/dist/tryout/snapshot/canonical.js +17 -0
- package/dist/tryout/snapshot/hash.d.ts +8 -0
- package/dist/tryout/snapshot/hash.js +19 -0
- package/dist/tryout/snapshot/spec.d.ts +46 -0
- package/dist/tryout/snapshot/spec.js +30 -0
- package/dist/tryout/spec.d.ts +13 -0
- package/dist/tryout/spec.js +15 -0
- package/package.json +506 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { compareCodeUnits } from "#contracts/text/order";
|
|
3
|
+
const COMPONENT_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9]*$/;
|
|
4
|
+
/** Renderer names are simple identifiers, never dotted member paths. */
|
|
5
|
+
export const RendererComponentNameSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((name) => COMPONENT_NAME_PATTERN.test(name), {
|
|
6
|
+
message: "Expected a component name matching /^[A-Za-z][A-Za-z0-9]*$/.",
|
|
7
|
+
})));
|
|
8
|
+
/** One named renderer capability and its positive contract version. */
|
|
9
|
+
export const RendererComponentRequirementSchema = Schema.Struct({
|
|
10
|
+
name: RendererComponentNameSchema,
|
|
11
|
+
version: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThan(0))),
|
|
12
|
+
});
|
|
13
|
+
/** Orders renderer requirements canonically by name and then version. */
|
|
14
|
+
function compareRequirements(left, right) {
|
|
15
|
+
return (compareCodeUnits(left.name, right.name) || left.version - right.version);
|
|
16
|
+
}
|
|
17
|
+
/** Checks that requirement pairs are unique and canonically ordered. */
|
|
18
|
+
function hasCanonicalRequirementPairs(requirements) {
|
|
19
|
+
for (let index = 1; index < requirements.length; index += 1) {
|
|
20
|
+
const previous = requirements[index - 1];
|
|
21
|
+
const current = requirements[index];
|
|
22
|
+
if (!(previous && current) || compareRequirements(previous, current) >= 0) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
/** Checks that each component name selects at most one version. */
|
|
29
|
+
function hasOneVersionPerComponent(requirements) {
|
|
30
|
+
for (let index = 1; index < requirements.length; index += 1) {
|
|
31
|
+
if (requirements[index - 1]?.name === requirements[index]?.name) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
/** Canonically sorts component requirements by name and then version. */
|
|
38
|
+
export function sortRendererComponentRequirements(requirements) {
|
|
39
|
+
return [...requirements].sort(compareRequirements);
|
|
40
|
+
}
|
|
41
|
+
const CanonicalRendererRequirementsSchema = Schema.Array(RendererComponentRequirementSchema).pipe(Schema.check(Schema.makeFilter(hasCanonicalRequirementPairs, {
|
|
42
|
+
message: "Expected unique renderer requirement pairs sorted by name and version.",
|
|
43
|
+
})));
|
|
44
|
+
/** Canonical runtime capabilities; an empty route domain is valid. */
|
|
45
|
+
export const RendererSupportedComponentsSchema = CanonicalRendererRequirementsSchema;
|
|
46
|
+
/** Canonical compiler choices; an empty route domain is valid. */
|
|
47
|
+
export const RendererAuthoringComponentsSchema = CanonicalRendererRequirementsSchema.pipe(Schema.check(Schema.makeFilter(hasOneVersionPerComponent, {
|
|
48
|
+
message: "Expected exactly one authoring version for each component name.",
|
|
49
|
+
})));
|
|
50
|
+
/** Canonical runtime capabilities; multiple versions per name are allowed. */
|
|
51
|
+
export const RendererManifestSupportedComponentsSchema = RendererSupportedComponentsSchema.pipe(Schema.check(Schema.isMinLength(1)));
|
|
52
|
+
/** Canonical compiler choices; exactly one version exists for every name. */
|
|
53
|
+
export const RendererManifestAuthoringComponentsSchema = RendererAuthoringComponentsSchema.pipe(Schema.check(Schema.isMinLength(1)));
|
|
54
|
+
/** Canonical artifact requirements; an artifact chooses one version per name. */
|
|
55
|
+
export const CompiledContentRequirementsSchema = CanonicalRendererRequirementsSchema.pipe(Schema.check(Schema.makeFilter(hasOneVersionPerComponent, {
|
|
56
|
+
message: "Expected at most one version for each required component.",
|
|
57
|
+
})));
|
|
58
|
+
/** Shared schema fields for one physical renderer registry capability. */
|
|
59
|
+
const RendererCapabilityFields = {
|
|
60
|
+
authoringComponents: RendererManifestAuthoringComponentsSchema,
|
|
61
|
+
supportedComponents: RendererManifestSupportedComponentsSchema,
|
|
62
|
+
};
|
|
63
|
+
const RendererCapabilityStructSchema = Schema.Struct(RendererCapabilityFields);
|
|
64
|
+
/** Checks that authoring pins select every supported component exactly once. */
|
|
65
|
+
export function hasCompleteRendererSelection(components) {
|
|
66
|
+
const authoringNames = new Set(components.authoringComponents.map(({ name }) => name));
|
|
67
|
+
const supportedNames = new Set(components.supportedComponents.map(({ name }) => name));
|
|
68
|
+
if (authoringNames.size !== supportedNames.size) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
return components.authoringComponents.every((selection) => components.supportedComponents.some((supported) => supported.name === selection.name &&
|
|
72
|
+
supported.version === selection.version));
|
|
73
|
+
}
|
|
74
|
+
/** One complete component contract owned by one physical registry scope. */
|
|
75
|
+
export const RendererCapabilitySchema = RendererCapabilityStructSchema.pipe(Schema.check(Schema.makeFilter(hasCompleteRendererSelection, {
|
|
76
|
+
message: "Expected one supported authoring selection for every component name.",
|
|
77
|
+
})));
|
|
78
|
+
/** More than one authoring version was selected for one component name. */
|
|
79
|
+
export class RendererAuthoringComponentDuplicateError extends Schema.TaggedError()("RendererAuthoringComponentDuplicateError", { componentName: RendererComponentNameSchema }) {
|
|
80
|
+
}
|
|
81
|
+
/** A runtime-supported component has no pinned authoring version. */
|
|
82
|
+
export class RendererAuthoringComponentMissingError extends Schema.TaggedError()("RendererAuthoringComponentMissingError", { componentName: RendererComponentNameSchema }) {
|
|
83
|
+
}
|
|
84
|
+
/** Authoring selected a component name absent from runtime support. */
|
|
85
|
+
export class RendererAuthoringComponentExtraError extends Schema.TaggedError()("RendererAuthoringComponentExtraError", { componentName: RendererComponentNameSchema }) {
|
|
86
|
+
}
|
|
87
|
+
/** Authoring selected a version absent from runtime support. */
|
|
88
|
+
export class RendererAuthoringComponentUnsupportedError extends Schema.TaggedError()("RendererAuthoringComponentUnsupportedError", {
|
|
89
|
+
componentName: RendererComponentNameSchema,
|
|
90
|
+
version: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThan(0))),
|
|
91
|
+
}) {
|
|
92
|
+
}
|
|
93
|
+
/** Authoring selections were not sorted by canonical component order. */
|
|
94
|
+
export class RendererAuthoringSelectionNonCanonicalError extends Schema.TaggedError()("RendererAuthoringSelectionNonCanonicalError", {
|
|
95
|
+
componentName: RendererComponentNameSchema,
|
|
96
|
+
index: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
97
|
+
}) {
|
|
98
|
+
}
|
|
99
|
+
/** Serializes one selected compiler component set in canonical order. */
|
|
100
|
+
export function canonicalizeRendererAuthoringSelection(authoringComponents) {
|
|
101
|
+
return JSON.stringify(authoringComponents.map(({ name, version }) => ({ name, version })));
|
|
102
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { type RendererCapability } from "#contracts/renderer/component";
|
|
3
|
+
/** Domain-scoped renderer wire version shared with Nakafa. */
|
|
4
|
+
export declare const RENDERER_CONTRACT_VERSION = "1.0.0";
|
|
5
|
+
/** Stable wire format for a domain-scoped Nakafa renderer manifest. */
|
|
6
|
+
export declare const RENDERER_MANIFEST_FORMAT = "nakafa-mdx-renderer-v1";
|
|
7
|
+
/** Canonical semantic version carried by a renderer runtime boundary. */
|
|
8
|
+
export declare const RendererContractVersionSchema: Schema.String;
|
|
9
|
+
export type RendererContractVersion = typeof RendererContractVersionSchema.Type;
|
|
10
|
+
/** One route-domain component contract with an exact real domain name. */
|
|
11
|
+
export declare const RendererDomainCapabilitySchema: Schema.Struct<{
|
|
12
|
+
readonly authoringComponents: Schema.$Array<Schema.Struct<{
|
|
13
|
+
readonly name: Schema.String;
|
|
14
|
+
readonly version: Schema.Finite;
|
|
15
|
+
}>>;
|
|
16
|
+
readonly name: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
17
|
+
readonly supportedComponents: Schema.$Array<Schema.Struct<{
|
|
18
|
+
readonly name: Schema.String;
|
|
19
|
+
readonly version: Schema.Finite;
|
|
20
|
+
}>>;
|
|
21
|
+
}>;
|
|
22
|
+
export type RendererDomainCapability = typeof RendererDomainCapabilitySchema.Type;
|
|
23
|
+
/** Canonical route domains that the deployed Nakafa app can publish. */
|
|
24
|
+
export declare const RendererPublishedDomainsSchema: Schema.$Array<Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>>;
|
|
25
|
+
export type RendererPublishedDomains = typeof RendererPublishedDomainsSchema.Type;
|
|
26
|
+
/** Sorts route-domain registries with cross-machine code-unit ordering. */
|
|
27
|
+
export declare function sortRendererDomains<T extends RendererDomainCapability>(domains: readonly T[]): T[];
|
|
28
|
+
/** Canonical persisted domains, including older known domain subsets. */
|
|
29
|
+
export declare const RendererManifestDomainsSchema: Schema.$Array<Schema.Struct<{
|
|
30
|
+
readonly authoringComponents: Schema.$Array<Schema.Struct<{
|
|
31
|
+
readonly name: Schema.String;
|
|
32
|
+
readonly version: Schema.Finite;
|
|
33
|
+
}>>;
|
|
34
|
+
readonly name: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
35
|
+
readonly supportedComponents: Schema.$Array<Schema.Struct<{
|
|
36
|
+
readonly name: Schema.String;
|
|
37
|
+
readonly version: Schema.Finite;
|
|
38
|
+
}>>;
|
|
39
|
+
}>>;
|
|
40
|
+
/** Complete current domain set required from a newly created live manifest. */
|
|
41
|
+
export declare const LiveRendererManifestDomainsSchema: Schema.$Array<Schema.Struct<{
|
|
42
|
+
readonly authoringComponents: Schema.$Array<Schema.Struct<{
|
|
43
|
+
readonly name: Schema.String;
|
|
44
|
+
readonly version: Schema.Finite;
|
|
45
|
+
}>>;
|
|
46
|
+
readonly name: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
47
|
+
readonly supportedComponents: Schema.$Array<Schema.Struct<{
|
|
48
|
+
readonly name: Schema.String;
|
|
49
|
+
readonly version: Schema.Finite;
|
|
50
|
+
}>>;
|
|
51
|
+
}>>;
|
|
52
|
+
/** Hash-authenticated renderer envelope persisted with one signed release. */
|
|
53
|
+
export declare const RendererManifestEnvelopeSchema: Schema.Struct<{
|
|
54
|
+
readonly base: Schema.Struct<{
|
|
55
|
+
authoringComponents: Schema.$Array<Schema.Struct<{
|
|
56
|
+
readonly name: Schema.String;
|
|
57
|
+
readonly version: Schema.Finite;
|
|
58
|
+
}>>;
|
|
59
|
+
supportedComponents: Schema.$Array<Schema.Struct<{
|
|
60
|
+
readonly name: Schema.String;
|
|
61
|
+
readonly version: Schema.Finite;
|
|
62
|
+
}>>;
|
|
63
|
+
}>;
|
|
64
|
+
readonly domains: Schema.$Array<Schema.Struct<{
|
|
65
|
+
readonly authoringComponents: Schema.$Array<Schema.Struct<{
|
|
66
|
+
readonly name: Schema.String;
|
|
67
|
+
readonly version: Schema.Finite;
|
|
68
|
+
}>>;
|
|
69
|
+
readonly name: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
70
|
+
readonly supportedComponents: Schema.$Array<Schema.Struct<{
|
|
71
|
+
readonly name: Schema.String;
|
|
72
|
+
readonly version: Schema.Finite;
|
|
73
|
+
}>>;
|
|
74
|
+
}>>;
|
|
75
|
+
readonly format: Schema.Literal<"nakafa-mdx-renderer-v1">;
|
|
76
|
+
readonly hash: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
77
|
+
readonly publishedDomains: Schema.$Array<Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>>;
|
|
78
|
+
readonly rendererContractVersion: Schema.Literal<"1.0.0">;
|
|
79
|
+
}>;
|
|
80
|
+
export type RendererManifestEnvelope = typeof RendererManifestEnvelopeSchema.Type;
|
|
81
|
+
declare const RendererDomainCapabilityMissingError_base: Schema.Class<RendererDomainCapabilityMissingError, Schema.TaggedStruct<"RendererDomainCapabilityMissingError", {
|
|
82
|
+
readonly rendererDomain: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
83
|
+
}>, import("effect/Cause").YieldableError>;
|
|
84
|
+
/** A persisted renderer envelope does not carry the requested domain. */
|
|
85
|
+
export declare class RendererDomainCapabilityMissingError extends RendererDomainCapabilityMissingError_base {
|
|
86
|
+
}
|
|
87
|
+
/** Selects the one physical route registry authorized for a document. */
|
|
88
|
+
export declare const selectRendererDomainCapability: (manifest: {
|
|
89
|
+
readonly base: {
|
|
90
|
+
readonly authoringComponents: readonly {
|
|
91
|
+
readonly name: string;
|
|
92
|
+
readonly version: number;
|
|
93
|
+
}[];
|
|
94
|
+
readonly supportedComponents: readonly {
|
|
95
|
+
readonly name: string;
|
|
96
|
+
readonly version: number;
|
|
97
|
+
}[];
|
|
98
|
+
};
|
|
99
|
+
readonly domains: readonly {
|
|
100
|
+
readonly authoringComponents: readonly {
|
|
101
|
+
readonly name: string;
|
|
102
|
+
readonly version: number;
|
|
103
|
+
}[];
|
|
104
|
+
readonly name: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math";
|
|
105
|
+
readonly supportedComponents: readonly {
|
|
106
|
+
readonly name: string;
|
|
107
|
+
readonly version: number;
|
|
108
|
+
}[];
|
|
109
|
+
}[];
|
|
110
|
+
readonly format: "nakafa-mdx-renderer-v1";
|
|
111
|
+
readonly hash: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
|
|
112
|
+
readonly publishedDomains: readonly ("ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math")[];
|
|
113
|
+
readonly rendererContractVersion: "1.0.0";
|
|
114
|
+
}, rendererDomain: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math") => Effect.Effect<{
|
|
115
|
+
readonly authoringComponents: readonly {
|
|
116
|
+
readonly name: string;
|
|
117
|
+
readonly version: number;
|
|
118
|
+
}[];
|
|
119
|
+
readonly name: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math";
|
|
120
|
+
readonly supportedComponents: readonly {
|
|
121
|
+
readonly name: string;
|
|
122
|
+
readonly version: number;
|
|
123
|
+
}[];
|
|
124
|
+
}, RendererDomainCapabilityMissingError, never>;
|
|
125
|
+
declare const RendererManifestHashComputeError_base: Schema.Class<RendererManifestHashComputeError, Schema.TaggedStruct<"RendererManifestHashComputeError", {
|
|
126
|
+
readonly cause: Schema.Unknown;
|
|
127
|
+
}>, import("effect/Cause").YieldableError>;
|
|
128
|
+
/** SHA-256 could not be calculated for the renderer contract bytes. */
|
|
129
|
+
export declare class RendererManifestHashComputeError extends RendererManifestHashComputeError_base {
|
|
130
|
+
}
|
|
131
|
+
declare const RendererManifestHashMismatchError_base: Schema.Class<RendererManifestHashMismatchError, Schema.TaggedStruct<"RendererManifestHashMismatchError", {
|
|
132
|
+
readonly actualHash: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
133
|
+
readonly expectedHash: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
134
|
+
}>, import("effect/Cause").YieldableError>;
|
|
135
|
+
/** The renderer envelope hash does not authenticate its canonical tuple. */
|
|
136
|
+
export declare class RendererManifestHashMismatchError extends RendererManifestHashMismatchError_base {
|
|
137
|
+
}
|
|
138
|
+
/** Serializes the exact domain-scoped renderer tuple covered by SHA-256. */
|
|
139
|
+
export declare function canonicalizeRendererManifestContract(input: {
|
|
140
|
+
readonly base: RendererCapability;
|
|
141
|
+
readonly domains: readonly RendererDomainCapability[];
|
|
142
|
+
readonly publishedDomains: RendererPublishedDomains;
|
|
143
|
+
}): string;
|
|
144
|
+
export {};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { Sha256HashSchema } from "#contracts/ids";
|
|
3
|
+
import { hasCompleteRendererSelection, RendererAuthoringComponentsSchema, RendererCapabilitySchema, RendererSupportedComponentsSchema, } from "#contracts/renderer/component";
|
|
4
|
+
import { RENDERER_DOMAINS, RendererDomainSchema, } from "#contracts/renderer/domain";
|
|
5
|
+
import { compareCodeUnits } from "#contracts/text/order";
|
|
6
|
+
const RENDERER_CONTRACT_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
7
|
+
/** Domain-scoped renderer wire version shared with Nakafa. */
|
|
8
|
+
export const RENDERER_CONTRACT_VERSION = "1.0.0";
|
|
9
|
+
/** Stable wire format for a domain-scoped Nakafa renderer manifest. */
|
|
10
|
+
export const RENDERER_MANIFEST_FORMAT = "nakafa-mdx-renderer-v1";
|
|
11
|
+
/** Canonical semantic version carried by a renderer runtime boundary. */
|
|
12
|
+
export const RendererContractVersionSchema = Schema.String.pipe(Schema.check(Schema.isPattern(RENDERER_CONTRACT_VERSION_PATTERN)));
|
|
13
|
+
/** One route-domain component contract with an exact real domain name. */
|
|
14
|
+
export const RendererDomainCapabilitySchema = Schema.Struct({
|
|
15
|
+
authoringComponents: RendererAuthoringComponentsSchema,
|
|
16
|
+
name: RendererDomainSchema,
|
|
17
|
+
supportedComponents: RendererSupportedComponentsSchema,
|
|
18
|
+
}).pipe(Schema.check(Schema.makeFilter(hasCompleteRendererSelection, {
|
|
19
|
+
message: "Expected one supported authoring selection for every domain component.",
|
|
20
|
+
})));
|
|
21
|
+
/** Checks published route domains are unique and ordered by code unit. */
|
|
22
|
+
function hasCanonicalPublishedDomains(domains) {
|
|
23
|
+
const canonical = [...domains].sort(compareCodeUnits);
|
|
24
|
+
return domains.every((domain, index) => domain === canonical[index] && domain !== domains[index - 1]);
|
|
25
|
+
}
|
|
26
|
+
/** Canonical route domains that the deployed Nakafa app can publish. */
|
|
27
|
+
export const RendererPublishedDomainsSchema = Schema.Array(RendererDomainSchema).pipe(Schema.check(Schema.isMinLength(1)), Schema.check(Schema.makeFilter(hasCanonicalPublishedDomains, {
|
|
28
|
+
message: "Expected unique published renderer domains in canonical order.",
|
|
29
|
+
})));
|
|
30
|
+
/** Sorts route-domain registries with cross-machine code-unit ordering. */
|
|
31
|
+
export function sortRendererDomains(domains) {
|
|
32
|
+
return [...domains].sort((left, right) => compareCodeUnits(left.name, right.name));
|
|
33
|
+
}
|
|
34
|
+
/** Checks persisted route domains are unique and canonically ordered. */
|
|
35
|
+
function hasCanonicalRendererDomains(domains) {
|
|
36
|
+
const canonical = sortRendererDomains(domains);
|
|
37
|
+
return domains.every((domain, index) => domain.name === canonical[index]?.name &&
|
|
38
|
+
domain.name !== domains[index - 1]?.name);
|
|
39
|
+
}
|
|
40
|
+
/** Canonical persisted domains, including older known domain subsets. */
|
|
41
|
+
export const RendererManifestDomainsSchema = Schema.Array(RendererDomainCapabilitySchema).pipe(Schema.check(Schema.isMinLength(1)), Schema.check(Schema.makeFilter(hasCanonicalRendererDomains, {
|
|
42
|
+
message: "Expected unique renderer domains in canonical order.",
|
|
43
|
+
})));
|
|
44
|
+
/** Complete current domain set required from a newly created live manifest. */
|
|
45
|
+
export const LiveRendererManifestDomainsSchema = RendererManifestDomainsSchema.pipe(Schema.check(Schema.makeFilter((domains) => domains.length === RENDERER_DOMAINS.length &&
|
|
46
|
+
domains.every(({ name }, index) => name === RENDERER_DOMAINS[index]), {
|
|
47
|
+
message: "Expected every live renderer domain in canonical order.",
|
|
48
|
+
})));
|
|
49
|
+
/** Keeps base component names out of every route-owned registry. */
|
|
50
|
+
function hasDistinctBaseComponents(manifest) {
|
|
51
|
+
const baseNames = new Set(manifest.base.supportedComponents.map(({ name }) => name));
|
|
52
|
+
for (const domain of manifest.domains) {
|
|
53
|
+
for (const { name } of domain.supportedComponents) {
|
|
54
|
+
if (baseNames.has(name)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
/** Keeps published domains bound to capabilities in the same envelope. */
|
|
62
|
+
function hasPublishedDomainCapabilities(manifest) {
|
|
63
|
+
const capabilities = new Set(manifest.domains.map(({ name }) => name));
|
|
64
|
+
return manifest.publishedDomains.every((domain) => capabilities.has(domain));
|
|
65
|
+
}
|
|
66
|
+
/** Hash-authenticated renderer envelope persisted with one signed release. */
|
|
67
|
+
export const RendererManifestEnvelopeSchema = Schema.Struct({
|
|
68
|
+
base: RendererCapabilitySchema,
|
|
69
|
+
domains: RendererManifestDomainsSchema,
|
|
70
|
+
format: Schema.Literal(RENDERER_MANIFEST_FORMAT),
|
|
71
|
+
hash: Sha256HashSchema,
|
|
72
|
+
publishedDomains: RendererPublishedDomainsSchema,
|
|
73
|
+
rendererContractVersion: Schema.Literal(RENDERER_CONTRACT_VERSION),
|
|
74
|
+
}).pipe(Schema.check(Schema.makeFilter(hasPublishedDomainCapabilities, {
|
|
75
|
+
message: "Expected every published renderer domain to have a capability.",
|
|
76
|
+
})), Schema.check(Schema.makeFilter(hasDistinctBaseComponents, {
|
|
77
|
+
message: "Expected base and route-domain component names to be disjoint.",
|
|
78
|
+
})));
|
|
79
|
+
/** A persisted renderer envelope does not carry the requested domain. */
|
|
80
|
+
export class RendererDomainCapabilityMissingError extends Schema.TaggedError()("RendererDomainCapabilityMissingError", { rendererDomain: RendererDomainSchema }) {
|
|
81
|
+
}
|
|
82
|
+
/** Selects the one physical route registry authorized for a document. */
|
|
83
|
+
export const selectRendererDomainCapability = Effect.fn("AksaraContracts.selectRendererDomainCapability")(function* (manifest, rendererDomain) {
|
|
84
|
+
const capability = manifest.domains.find(({ name }) => name === rendererDomain);
|
|
85
|
+
if (!capability) {
|
|
86
|
+
return yield* new RendererDomainCapabilityMissingError({ rendererDomain });
|
|
87
|
+
}
|
|
88
|
+
return capability;
|
|
89
|
+
});
|
|
90
|
+
/** SHA-256 could not be calculated for the renderer contract bytes. */
|
|
91
|
+
export class RendererManifestHashComputeError extends Schema.TaggedError()("RendererManifestHashComputeError", { cause: Schema.Unknown }) {
|
|
92
|
+
}
|
|
93
|
+
/** The renderer envelope hash does not authenticate its canonical tuple. */
|
|
94
|
+
export class RendererManifestHashMismatchError extends Schema.TaggedError()("RendererManifestHashMismatchError", {
|
|
95
|
+
actualHash: Sha256HashSchema,
|
|
96
|
+
expectedHash: Sha256HashSchema,
|
|
97
|
+
}) {
|
|
98
|
+
}
|
|
99
|
+
/** Serializes the exact domain-scoped renderer tuple covered by SHA-256. */
|
|
100
|
+
export function canonicalizeRendererManifestContract(input) {
|
|
101
|
+
/** Copies one registry capability into exact canonical wire fields. */
|
|
102
|
+
const capability = (value) => ({
|
|
103
|
+
authoringComponents: value.authoringComponents.map(({ name, version }) => ({
|
|
104
|
+
name,
|
|
105
|
+
version,
|
|
106
|
+
})),
|
|
107
|
+
supportedComponents: value.supportedComponents.map(({ name, version }) => ({
|
|
108
|
+
name,
|
|
109
|
+
version,
|
|
110
|
+
})),
|
|
111
|
+
});
|
|
112
|
+
return JSON.stringify([
|
|
113
|
+
RENDERER_MANIFEST_FORMAT,
|
|
114
|
+
RENDERER_CONTRACT_VERSION,
|
|
115
|
+
capability(input.base),
|
|
116
|
+
sortRendererDomains(input.domains).map(({ name, ...domain }) => ({
|
|
117
|
+
name,
|
|
118
|
+
...capability(domain),
|
|
119
|
+
})),
|
|
120
|
+
input.publishedDomains,
|
|
121
|
+
]);
|
|
122
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** Renderer domains backed by real route-owned Nakafa registries. */
|
|
3
|
+
export declare const RENDERER_DOMAINS: readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"];
|
|
4
|
+
/** Exact route-domain identity carried by authored and compiled content. */
|
|
5
|
+
export declare const RendererDomainSchema: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
6
|
+
export type RendererDomain = typeof RendererDomainSchema.Type;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** Renderer domains backed by real route-owned Nakafa registries. */
|
|
3
|
+
export const RENDERER_DOMAINS = [
|
|
4
|
+
"ai-ds",
|
|
5
|
+
"biology",
|
|
6
|
+
"chemistry",
|
|
7
|
+
"mathematics",
|
|
8
|
+
"physics",
|
|
9
|
+
"politics",
|
|
10
|
+
"site",
|
|
11
|
+
"snbt-general",
|
|
12
|
+
"snbt-math",
|
|
13
|
+
"snbt-plain",
|
|
14
|
+
"snbt-quant",
|
|
15
|
+
"tka-math",
|
|
16
|
+
];
|
|
17
|
+
/** Exact route-domain identity carried by authored and compiled content. */
|
|
18
|
+
export const RendererDomainSchema = Schema.Literals(RENDERER_DOMAINS);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { RendererManifestHashComputeError, RendererManifestHashMismatchError } from "#contracts/renderer/contract";
|
|
3
|
+
/** Creates a canonical renderer envelope from real registry capabilities. */
|
|
4
|
+
export declare const createRendererManifest: (input: unknown) => Effect.Effect<{
|
|
5
|
+
readonly base: {
|
|
6
|
+
readonly authoringComponents: readonly {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly version: number;
|
|
9
|
+
}[];
|
|
10
|
+
readonly supportedComponents: readonly {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly version: number;
|
|
13
|
+
}[];
|
|
14
|
+
};
|
|
15
|
+
readonly domains: readonly {
|
|
16
|
+
readonly authoringComponents: readonly {
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly version: number;
|
|
19
|
+
}[];
|
|
20
|
+
readonly name: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math";
|
|
21
|
+
readonly supportedComponents: readonly {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly version: number;
|
|
24
|
+
}[];
|
|
25
|
+
}[];
|
|
26
|
+
readonly format: "nakafa-mdx-renderer-v1";
|
|
27
|
+
readonly hash: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
|
|
28
|
+
readonly publishedDomains: readonly ("ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math")[];
|
|
29
|
+
readonly rendererContractVersion: "1.0.0";
|
|
30
|
+
}, import("../errors.js").ContractDecodeError | import("#contracts/renderer/component").RendererAuthoringComponentDuplicateError | import("#contracts/renderer/component").RendererAuthoringComponentExtraError | import("#contracts/renderer/component").RendererAuthoringComponentMissingError | import("#contracts/renderer/component").RendererAuthoringComponentUnsupportedError | import("#contracts/renderer/component").RendererAuthoringSelectionNonCanonicalError | RendererManifestHashComputeError, never>;
|
|
31
|
+
/** Verifies one persisted envelope, including a known historical domain subset. */
|
|
32
|
+
export declare const validateRendererManifestHash: (input: unknown) => Effect.Effect<{
|
|
33
|
+
readonly base: {
|
|
34
|
+
readonly authoringComponents: readonly {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
readonly version: number;
|
|
37
|
+
}[];
|
|
38
|
+
readonly supportedComponents: readonly {
|
|
39
|
+
readonly name: string;
|
|
40
|
+
readonly version: number;
|
|
41
|
+
}[];
|
|
42
|
+
};
|
|
43
|
+
readonly domains: readonly {
|
|
44
|
+
readonly authoringComponents: readonly {
|
|
45
|
+
readonly name: string;
|
|
46
|
+
readonly version: number;
|
|
47
|
+
}[];
|
|
48
|
+
readonly name: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math";
|
|
49
|
+
readonly supportedComponents: readonly {
|
|
50
|
+
readonly name: string;
|
|
51
|
+
readonly version: number;
|
|
52
|
+
}[];
|
|
53
|
+
}[];
|
|
54
|
+
readonly format: "nakafa-mdx-renderer-v1";
|
|
55
|
+
readonly hash: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
|
|
56
|
+
readonly publishedDomains: readonly ("ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math")[];
|
|
57
|
+
readonly rendererContractVersion: "1.0.0";
|
|
58
|
+
}, import("../errors.js").ContractDecodeError | import("#contracts/renderer/component").RendererAuthoringComponentDuplicateError | import("#contracts/renderer/component").RendererAuthoringComponentExtraError | import("#contracts/renderer/component").RendererAuthoringComponentMissingError | import("#contracts/renderer/component").RendererAuthoringComponentUnsupportedError | import("#contracts/renderer/component").RendererAuthoringSelectionNonCanonicalError | RendererManifestHashComputeError | RendererManifestHashMismatchError, never>;
|
|
59
|
+
/** Verifies one complete manifest supplied by a current live renderer. */
|
|
60
|
+
export declare const validateLiveRendererManifestHash: (input: unknown) => Effect.Effect<{
|
|
61
|
+
base: {
|
|
62
|
+
readonly authoringComponents: readonly {
|
|
63
|
+
readonly name: string;
|
|
64
|
+
readonly version: number;
|
|
65
|
+
}[];
|
|
66
|
+
readonly supportedComponents: readonly {
|
|
67
|
+
readonly name: string;
|
|
68
|
+
readonly version: number;
|
|
69
|
+
}[];
|
|
70
|
+
};
|
|
71
|
+
format: "nakafa-mdx-renderer-v1";
|
|
72
|
+
hash: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
|
|
73
|
+
publishedDomains: readonly ("ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math")[];
|
|
74
|
+
rendererContractVersion: "1.0.0";
|
|
75
|
+
domains: readonly {
|
|
76
|
+
readonly authoringComponents: readonly {
|
|
77
|
+
readonly name: string;
|
|
78
|
+
readonly version: number;
|
|
79
|
+
}[];
|
|
80
|
+
readonly name: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math";
|
|
81
|
+
readonly supportedComponents: readonly {
|
|
82
|
+
readonly name: string;
|
|
83
|
+
readonly version: number;
|
|
84
|
+
}[];
|
|
85
|
+
}[];
|
|
86
|
+
}, import("../errors.js").ContractDecodeError | import("#contracts/renderer/component").RendererAuthoringComponentDuplicateError | import("#contracts/renderer/component").RendererAuthoringComponentExtraError | import("#contracts/renderer/component").RendererAuthoringComponentMissingError | import("#contracts/renderer/component").RendererAuthoringComponentUnsupportedError | import("#contracts/renderer/component").RendererAuthoringSelectionNonCanonicalError | RendererManifestHashComputeError | RendererManifestHashMismatchError, never>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { decodeContract } from "#contracts/decode";
|
|
3
|
+
import { hashText } from "#contracts/hash/text";
|
|
4
|
+
import { Sha256HashSchema } from "#contracts/ids";
|
|
5
|
+
import { RendererComponentRequirementSchema } from "#contracts/renderer/component";
|
|
6
|
+
import { canonicalizeRendererManifestContract, LiveRendererManifestDomainsSchema, RENDERER_CONTRACT_VERSION, RENDERER_MANIFEST_FORMAT, RendererManifestEnvelopeSchema, RendererManifestHashComputeError, RendererManifestHashMismatchError, RendererPublishedDomainsSchema, } from "#contracts/renderer/contract";
|
|
7
|
+
import { RendererDomainSchema, } from "#contracts/renderer/domain";
|
|
8
|
+
import { normalizeRendererSelection } from "#contracts/renderer/selection";
|
|
9
|
+
import { compareCodeUnits } from "#contracts/text/order";
|
|
10
|
+
const CapabilityCreationFields = {
|
|
11
|
+
authoringComponents: Schema.Array(RendererComponentRequirementSchema),
|
|
12
|
+
supportedComponents: Schema.Array(RendererComponentRequirementSchema),
|
|
13
|
+
};
|
|
14
|
+
const RendererManifestCreationSchema = Schema.Struct({
|
|
15
|
+
base: Schema.Struct(CapabilityCreationFields),
|
|
16
|
+
domains: Schema.Array(Schema.Struct({ name: RendererDomainSchema, ...CapabilityCreationFields })),
|
|
17
|
+
publishedDomains: Schema.Array(RendererDomainSchema),
|
|
18
|
+
});
|
|
19
|
+
const RendererManifestWireSchema = Schema.Struct({
|
|
20
|
+
...RendererManifestCreationSchema.fields,
|
|
21
|
+
format: Schema.Literal(RENDERER_MANIFEST_FORMAT),
|
|
22
|
+
hash: Sha256HashSchema,
|
|
23
|
+
rendererContractVersion: Schema.Literal(RENDERER_CONTRACT_VERSION),
|
|
24
|
+
});
|
|
25
|
+
/** Sorts and decodes the exact route domains exposed by the deployed app. */
|
|
26
|
+
const normalizePublishedDomains = Effect.fn("AksaraContracts.normalizePublishedDomains")((domains) => decodeContract(RendererPublishedDomainsSchema, "RendererPublishedDomains", [...domains].sort(compareCodeUnits)));
|
|
27
|
+
/** Hashes the canonical base and domain-scoped renderer contract. */
|
|
28
|
+
const hashRendererContract = Effect.fn("AksaraContracts.hashRendererContract")((input) => hashText(canonicalizeRendererManifestContract(input)).pipe(Effect.mapError(({ cause }) => new RendererManifestHashComputeError({ cause }))));
|
|
29
|
+
/** Creates a canonical renderer envelope from real registry capabilities. */
|
|
30
|
+
export const createRendererManifest = Effect.fn("AksaraContracts.createRendererManifest")((input) => decodeContract(RendererManifestCreationSchema, "RendererManifestCreation", input).pipe(Effect.flatMap((wire) => Effect.all({
|
|
31
|
+
contract: normalizeRendererSelection(wire).pipe(Effect.flatMap((contract) => decodeContract(LiveRendererManifestDomainsSchema, "LiveRendererManifestDomains", contract.domains).pipe(Effect.map((domains) => ({ ...contract, domains }))))),
|
|
32
|
+
publishedDomains: normalizePublishedDomains(wire.publishedDomains),
|
|
33
|
+
})), Effect.flatMap(({ contract, publishedDomains }) => hashRendererContract({ ...contract, publishedDomains }).pipe(Effect.flatMap((hash) => decodeContract(RendererManifestEnvelopeSchema, "RendererManifestEnvelope", {
|
|
34
|
+
...contract,
|
|
35
|
+
format: RENDERER_MANIFEST_FORMAT,
|
|
36
|
+
hash,
|
|
37
|
+
publishedDomains,
|
|
38
|
+
rendererContractVersion: RENDERER_CONTRACT_VERSION,
|
|
39
|
+
}))))));
|
|
40
|
+
/** Verifies one persisted envelope, including a known historical domain subset. */
|
|
41
|
+
export const validateRendererManifestHash = Effect.fn("AksaraContracts.validateRendererManifestHash")((input) => decodeContract(RendererManifestWireSchema, "RendererManifestEnvelope", input).pipe(Effect.flatMap((wire) => Effect.all({
|
|
42
|
+
contract: normalizeRendererSelection(wire),
|
|
43
|
+
publishedDomains: normalizePublishedDomains(wire.publishedDomains),
|
|
44
|
+
}).pipe(Effect.flatMap(({ contract, publishedDomains }) => hashRendererContract({ ...contract, publishedDomains }).pipe(Effect.filterOrFail((actualHash) => actualHash === wire.hash, (actualHash) => new RendererManifestHashMismatchError({
|
|
45
|
+
actualHash,
|
|
46
|
+
expectedHash: wire.hash,
|
|
47
|
+
})), Effect.flatMap(() => decodeContract(RendererManifestEnvelopeSchema, "RendererManifestEnvelope", { ...wire, ...contract, publishedDomains }))))))));
|
|
48
|
+
/** Verifies one complete manifest supplied by a current live renderer. */
|
|
49
|
+
export const validateLiveRendererManifestHash = Effect.fn("AksaraContracts.validateLiveRendererManifestHash")((input) => validateRendererManifestHash(input).pipe(Effect.flatMap((manifest) => decodeContract(LiveRendererManifestDomainsSchema, "LiveRendererManifestDomains", manifest.domains).pipe(Effect.map((domains) => ({ ...manifest, domains }))))));
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { RendererAuthoringComponentDuplicateError, RendererAuthoringComponentExtraError, RendererAuthoringComponentMissingError, RendererAuthoringComponentUnsupportedError, RendererAuthoringSelectionNonCanonicalError, type RendererComponentRequirement } from "#contracts/renderer/component";
|
|
3
|
+
import type { RendererDomain } from "#contracts/renderer/domain";
|
|
4
|
+
/** Unnormalized component contract accepted at the manifest boundary. */
|
|
5
|
+
export interface RendererCapabilityInput {
|
|
6
|
+
readonly authoringComponents: readonly RendererComponentRequirement[];
|
|
7
|
+
readonly supportedComponents: readonly RendererComponentRequirement[];
|
|
8
|
+
}
|
|
9
|
+
/** Unnormalized route-domain contract accepted at the manifest boundary. */
|
|
10
|
+
export interface RendererDomainInput extends RendererCapabilityInput {
|
|
11
|
+
readonly name: RendererDomain;
|
|
12
|
+
}
|
|
13
|
+
/** Normalizes the exact base plus every canonical route-domain registry. */
|
|
14
|
+
export declare const normalizeRendererSelection: (input: {
|
|
15
|
+
readonly base: RendererCapabilityInput;
|
|
16
|
+
readonly domains: readonly RendererDomainInput[];
|
|
17
|
+
}) => Effect.Effect<{
|
|
18
|
+
base: {
|
|
19
|
+
readonly authoringComponents: readonly {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly version: number;
|
|
22
|
+
}[];
|
|
23
|
+
readonly supportedComponents: readonly {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly version: number;
|
|
26
|
+
}[];
|
|
27
|
+
};
|
|
28
|
+
domains: readonly {
|
|
29
|
+
readonly authoringComponents: readonly {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly version: number;
|
|
32
|
+
}[];
|
|
33
|
+
readonly name: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math";
|
|
34
|
+
readonly supportedComponents: readonly {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
readonly version: number;
|
|
37
|
+
}[];
|
|
38
|
+
}[];
|
|
39
|
+
}, import("../errors.js").ContractDecodeError | RendererAuthoringComponentDuplicateError | RendererAuthoringComponentExtraError | RendererAuthoringComponentMissingError | RendererAuthoringComponentUnsupportedError | RendererAuthoringSelectionNonCanonicalError, never>;
|