@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,92 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { SignedContentArtifactSchema } from "#contracts/content";
|
|
3
|
+
import { ContentKeySchema, Sha256HashSchema } from "#contracts/ids";
|
|
4
|
+
import { RendererComponentNameSchema } from "#contracts/renderer/component";
|
|
5
|
+
import { RendererContractVersionSchema, RendererManifestEnvelopeSchema, } from "#contracts/renderer/contract";
|
|
6
|
+
import { RendererDomainSchema } from "#contracts/renderer/domain";
|
|
7
|
+
/**
|
|
8
|
+
* Complete server-only input needed to authenticate one compiled artifact.
|
|
9
|
+
* `rendererContractVersion` comes from the active release because payloads do
|
|
10
|
+
* not duplicate that release-scoped value.
|
|
11
|
+
*/
|
|
12
|
+
export const ArtifactVerificationRequestSchema = Schema.Struct({
|
|
13
|
+
artifact: SignedContentArtifactSchema,
|
|
14
|
+
rendererContractVersion: RendererContractVersionSchema,
|
|
15
|
+
rendererManifest: RendererManifestEnvelopeSchema,
|
|
16
|
+
});
|
|
17
|
+
/** Unknown artifact input did not exactly satisfy the verification contract. */
|
|
18
|
+
export class ArtifactVerificationDecodeError extends Schema.TaggedError()("ArtifactVerificationDecodeError", {
|
|
19
|
+
message: Schema.Literal("Artifact verification input does not satisfy its exact wire contract."),
|
|
20
|
+
}) {
|
|
21
|
+
}
|
|
22
|
+
/** A signed artifact exceeded the canonical UTF-8 wire ceiling. */
|
|
23
|
+
export class ArtifactVerificationByteLimitError extends Schema.TaggedError()("ArtifactVerificationByteLimitError", {
|
|
24
|
+
actualBytes: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
25
|
+
maxBytes: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThan(0))),
|
|
26
|
+
}) {
|
|
27
|
+
}
|
|
28
|
+
/** Declared compiled bytes differ from the authenticated function body. */
|
|
29
|
+
export class ArtifactCompiledByteLengthMismatchError extends Schema.TaggedError()("ArtifactCompiledByteLengthMismatchError", {
|
|
30
|
+
actualBytes: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
31
|
+
contentKey: ContentKeySchema,
|
|
32
|
+
declaredBytes: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
33
|
+
}) {
|
|
34
|
+
}
|
|
35
|
+
/** One authenticated payload field exceeded its shared runtime ceiling. */
|
|
36
|
+
export class ArtifactPayloadFieldByteLimitError extends Schema.TaggedError()("ArtifactPayloadFieldByteLimitError", {
|
|
37
|
+
actualBytes: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
38
|
+
contentKey: ContentKeySchema,
|
|
39
|
+
field: Schema.Literals([
|
|
40
|
+
"rawMdx",
|
|
41
|
+
"compiledCode",
|
|
42
|
+
"plainText",
|
|
43
|
+
"canonicalPayload",
|
|
44
|
+
]),
|
|
45
|
+
maxBytes: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThan(0))),
|
|
46
|
+
}) {
|
|
47
|
+
}
|
|
48
|
+
/** SHA-256 computation failed before authenticity could be established. */
|
|
49
|
+
export class ArtifactHashComputationError extends Schema.TaggedError()("ArtifactHashComputationError", { contentKey: ContentKeySchema }) {
|
|
50
|
+
}
|
|
51
|
+
/** The signed artifact hash does not identify its canonical payload. */
|
|
52
|
+
export class ArtifactHashMismatchError extends Schema.TaggedError()("ArtifactHashMismatchError", {
|
|
53
|
+
actualHash: Sha256HashSchema,
|
|
54
|
+
contentKey: ContentKeySchema,
|
|
55
|
+
expectedHash: Sha256HashSchema,
|
|
56
|
+
}) {
|
|
57
|
+
}
|
|
58
|
+
/** SHA-256 could not be calculated for the authenticated authored source. */
|
|
59
|
+
export class ArtifactSourceHashComputationError extends Schema.TaggedError()("ArtifactSourceHashComputationError", { contentKey: ContentKeySchema }) {
|
|
60
|
+
}
|
|
61
|
+
/** The authenticated source hash does not identify the complete raw MDX. */
|
|
62
|
+
export class ArtifactSourceHashMismatchError extends Schema.TaggedError()("ArtifactSourceHashMismatchError", {
|
|
63
|
+
actualHash: Sha256HashSchema,
|
|
64
|
+
contentKey: ContentKeySchema,
|
|
65
|
+
expectedHash: Sha256HashSchema,
|
|
66
|
+
}) {
|
|
67
|
+
}
|
|
68
|
+
/** The runtime and hash-validated renderer envelope disagree globally. */
|
|
69
|
+
export class RendererContractVersionMismatchError extends Schema.TaggedError()("RendererContractVersionMismatchError", {
|
|
70
|
+
actualVersion: RendererContractVersionSchema,
|
|
71
|
+
expectedVersion: RendererContractVersionSchema,
|
|
72
|
+
}) {
|
|
73
|
+
}
|
|
74
|
+
/** A custom component required by the artifact is absent from the renderer. */
|
|
75
|
+
export class ArtifactRendererComponentMissingError extends Schema.TaggedError()("ArtifactRendererComponentMissingError", {
|
|
76
|
+
componentName: RendererComponentNameSchema,
|
|
77
|
+
contentKey: ContentKeySchema,
|
|
78
|
+
}) {
|
|
79
|
+
}
|
|
80
|
+
/** The renderer does not implement the exact required component version. */
|
|
81
|
+
export class ArtifactRendererVersionUnsupportedError extends Schema.TaggedError()("ArtifactRendererVersionUnsupportedError", {
|
|
82
|
+
componentName: RendererComponentNameSchema,
|
|
83
|
+
contentKey: ContentKeySchema,
|
|
84
|
+
requiredVersion: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThan(0))),
|
|
85
|
+
}) {
|
|
86
|
+
}
|
|
87
|
+
/** The deployed Nakafa app cannot route this artifact's renderer domain. */
|
|
88
|
+
export class ArtifactRendererDomainUnpublishedError extends Schema.TaggedError()("ArtifactRendererDomainUnpublishedError", {
|
|
89
|
+
contentKey: ContentKeySchema,
|
|
90
|
+
rendererDomain: RendererDomainSchema,
|
|
91
|
+
}) {
|
|
92
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { ArtifactVerificationDecodeError } from "#contracts/artifact/spec";
|
|
3
|
+
/** Authenticates one artifact and its exact renderer compatibility contract. */
|
|
4
|
+
export declare const verifySignedContentArtifact: (input: unknown) => Effect.Effect<{
|
|
5
|
+
readonly artifactHash: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
|
|
6
|
+
readonly keyId: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSigningKeyId">;
|
|
7
|
+
readonly payload: {
|
|
8
|
+
readonly artifactLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraArtifactLocale">;
|
|
9
|
+
readonly byteLength: number;
|
|
10
|
+
readonly compiledCode: string;
|
|
11
|
+
readonly compilerConfigHash: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
|
|
12
|
+
readonly compilerVersion: "0.1.0";
|
|
13
|
+
readonly contentKey: string & import("effect/Brand").Brand<"@NakafaAI/AksaraContentKey">;
|
|
14
|
+
readonly format: "mdx-function-body";
|
|
15
|
+
readonly mdxCompilerVersion: "3.1.1";
|
|
16
|
+
readonly plainText: string;
|
|
17
|
+
readonly rawMdx: string;
|
|
18
|
+
readonly rendererDomain: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math";
|
|
19
|
+
readonly requiredComponents: readonly {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly version: number;
|
|
22
|
+
}[];
|
|
23
|
+
readonly sourceHash: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
|
|
24
|
+
};
|
|
25
|
+
readonly signature: string & import("effect/Brand").Brand<"@NakafaAI/AksaraEd25519Signature">;
|
|
26
|
+
}, import("#contracts/artifact/spec").ArtifactCompiledByteLengthMismatchError | import("#contracts/artifact/spec").ArtifactHashComputationError | import("#contracts/artifact/spec").ArtifactHashMismatchError | import("#contracts/artifact/spec").ArtifactPayloadFieldByteLimitError | import("#contracts/artifact/spec").ArtifactRendererComponentMissingError | import("#contracts/artifact/spec").ArtifactRendererDomainUnpublishedError | import("#contracts/artifact/spec").ArtifactRendererVersionUnsupportedError | import("#contracts/artifact/spec").ArtifactSourceHashComputationError | import("#contracts/artifact/spec").ArtifactSourceHashMismatchError | import("#contracts/artifact/spec").ArtifactVerificationByteLimitError | ArtifactVerificationDecodeError | import("../errors.js").ContractDecodeError | import("../signature/spec.js").PublicKeyParseError | import("../signature/spec.js").PublicKeyTypeError | import("../renderer/component.js").RendererAuthoringComponentDuplicateError | import("../renderer/component.js").RendererAuthoringComponentExtraError | import("../renderer/component.js").RendererAuthoringComponentMissingError | import("../renderer/component.js").RendererAuthoringComponentUnsupportedError | import("../renderer/component.js").RendererAuthoringSelectionNonCanonicalError | import("#contracts/artifact/spec").RendererContractVersionMismatchError | import("../renderer/contract.js").RendererDomainCapabilityMissingError | import("../renderer/contract.js").RendererManifestHashComputeError | import("../renderer/contract.js").RendererManifestHashMismatchError | import("../signature/spec.js").SignatureCheckError | import("../signature/spec.js").SignatureInvalidError | import("../signature/spec.js").SigningKeyNotFoundError | import("../signature/spec.js").SigningKeyResolutionError, import("../signature/spec.js").ContentVerificationKeyResolver>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { verifySignedContentArtifactIntegrity } from "#contracts/artifact/integrity";
|
|
3
|
+
import { ArtifactVerificationDecodeError, ArtifactVerificationRequestSchema, } from "#contracts/artifact/spec";
|
|
4
|
+
import { verifyContentRendererCompatibility } from "#contracts/renderer/compatibility";
|
|
5
|
+
/** Authenticates one artifact and its exact renderer compatibility contract. */
|
|
6
|
+
export const verifySignedContentArtifact = Effect.fn("AksaraContracts.verifySignedContentArtifact")((input) => Schema.decodeUnknownEffect(ArtifactVerificationRequestSchema)(input, {
|
|
7
|
+
onExcessProperty: "error",
|
|
8
|
+
}).pipe(Effect.mapError(() => new ArtifactVerificationDecodeError({
|
|
9
|
+
message: "Artifact verification input does not satisfy its exact wire contract.",
|
|
10
|
+
})), Effect.flatMap((request) => Effect.gen(function* () {
|
|
11
|
+
const artifact = yield* verifySignedContentArtifactIntegrity(request.artifact);
|
|
12
|
+
yield* verifyContentRendererCompatibility({
|
|
13
|
+
payload: artifact.payload,
|
|
14
|
+
rendererContractVersion: request.rendererContractVersion,
|
|
15
|
+
rendererManifest: request.rendererManifest,
|
|
16
|
+
});
|
|
17
|
+
return artifact;
|
|
18
|
+
}))));
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { type ContentFamily } from "#contracts/content";
|
|
3
|
+
import { type ReleaseId, type Sha256Hash } from "#contracts/ids";
|
|
4
|
+
/** Global content-runtime tag always invalidated before narrower tags. */
|
|
5
|
+
export declare const CONTENT_CACHE_GLOBAL_TAG = "content-runtime";
|
|
6
|
+
/** Maximum exact artifact tags carried with global and family cache tags. */
|
|
7
|
+
export declare const MAX_CONTENT_CACHE_ARTIFACTS = 98;
|
|
8
|
+
/** One immutable published-artifact cache tag derived only from its hash. */
|
|
9
|
+
export declare const ArtifactCacheTagSchema: Schema.brand<Schema.String, "@NakafaAI/AksaraArtifactCacheTag">;
|
|
10
|
+
export type ArtifactCacheTag = typeof ArtifactCacheTagSchema.Type;
|
|
11
|
+
/** One exact content-family cache tag derived from the family contract. */
|
|
12
|
+
export declare const ContentFamilyCacheTagSchema: Schema.brand<Schema.String, "@NakafaAI/AksaraContentFamilyCacheTag">;
|
|
13
|
+
export type ContentFamilyCacheTag = typeof ContentFamilyCacheTagSchema.Type;
|
|
14
|
+
/**
|
|
15
|
+
* Ordered cache tags shared by Aksara and Nakafa.
|
|
16
|
+
*
|
|
17
|
+
* Global and exact family tags come first; remaining tags name exact changed
|
|
18
|
+
* artifacts while keeping one invalidation request at or below 100 tags.
|
|
19
|
+
*/
|
|
20
|
+
export declare const ContentCacheTagsSchema: Schema.TupleWithRest<Schema.Tuple<readonly [Schema.Literal<"content-runtime">, Schema.brand<Schema.String, "@NakafaAI/AksaraContentFamilyCacheTag">]>, readonly [Schema.brand<Schema.String, "@NakafaAI/AksaraArtifactCacheTag">]>;
|
|
21
|
+
export type ContentCacheTags = typeof ContentCacheTagsSchema.Type;
|
|
22
|
+
/** One changed family plus its optional newly published immutable artifact. */
|
|
23
|
+
export declare const ContentCacheChangeSchema: Schema.Struct<{
|
|
24
|
+
readonly artifactHash: Schema.optional<Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">>;
|
|
25
|
+
readonly family: Schema.Literals<readonly ["article", "material", "page", "question"]>;
|
|
26
|
+
}>;
|
|
27
|
+
export type ContentCacheChange = typeof ContentCacheChangeSchema.Type;
|
|
28
|
+
/** Derives the canonical cache tag for one already-canonical artifact hash. */
|
|
29
|
+
export declare function makeArtifactCacheTag(hash: Sha256Hash): ArtifactCacheTag;
|
|
30
|
+
/** Derives the canonical cache tag for one implemented content family. */
|
|
31
|
+
export declare function makeContentFamilyCacheTag(family: ContentFamily): ContentFamilyCacheTag;
|
|
32
|
+
/** One release-bound, family-exact cache invalidation request. */
|
|
33
|
+
export declare const ContentCacheRequestSchema: Schema.Struct<{
|
|
34
|
+
readonly family: Schema.Literals<readonly ["article", "material", "page", "question"]>;
|
|
35
|
+
readonly releaseId: Schema.brand<Schema.String, "@NakafaAI/AksaraReleaseId">;
|
|
36
|
+
readonly tags: Schema.TupleWithRest<Schema.Tuple<readonly [Schema.Literal<"content-runtime">, Schema.brand<Schema.String, "@NakafaAI/AksaraContentFamilyCacheTag">]>, readonly [Schema.brand<Schema.String, "@NakafaAI/AksaraArtifactCacheTag">]>;
|
|
37
|
+
}>;
|
|
38
|
+
export type ContentCacheRequest = typeof ContentCacheRequestSchema.Type;
|
|
39
|
+
/** Nakafa proof that one exact release-bound invalidation completed. */
|
|
40
|
+
export declare const ContentCacheReceiptSchema: Schema.Struct<{
|
|
41
|
+
readonly family: Schema.Literals<readonly ["article", "material", "page", "question"]>;
|
|
42
|
+
readonly releaseId: Schema.brand<Schema.String, "@NakafaAI/AksaraReleaseId">;
|
|
43
|
+
readonly revalidated: Schema.Literal<true>;
|
|
44
|
+
readonly tags: Schema.TupleWithRest<Schema.Tuple<readonly [Schema.Literal<"content-runtime">, Schema.brand<Schema.String, "@NakafaAI/AksaraContentFamilyCacheTag">]>, readonly [Schema.brand<Schema.String, "@NakafaAI/AksaraArtifactCacheTag">]>;
|
|
45
|
+
}>;
|
|
46
|
+
export type ContentCacheReceipt = typeof ContentCacheReceiptSchema.Type;
|
|
47
|
+
/** Builds one ordered invalidation request for one exact content family. */
|
|
48
|
+
export declare function makeContentCacheRequest(input: {
|
|
49
|
+
readonly artifactHashes: readonly Sha256Hash[];
|
|
50
|
+
readonly family: ContentFamily;
|
|
51
|
+
readonly releaseId: ReleaseId;
|
|
52
|
+
}): ContentCacheRequest;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { ContentFamilySchema } from "#contracts/content";
|
|
3
|
+
import { ReleaseIdSchema, Sha256HashSchema, } from "#contracts/ids";
|
|
4
|
+
/** Global content-runtime tag always invalidated before narrower tags. */
|
|
5
|
+
export const CONTENT_CACHE_GLOBAL_TAG = "content-runtime";
|
|
6
|
+
const ARTIFACT_CACHE_PREFIX = "content-artifact:";
|
|
7
|
+
const FAMILY_CACHE_PREFIX = "content-family:";
|
|
8
|
+
/** Maximum exact artifact tags carried with global and family cache tags. */
|
|
9
|
+
export const MAX_CONTENT_CACHE_ARTIFACTS = 98;
|
|
10
|
+
/** One immutable published-artifact cache tag derived only from its hash. */
|
|
11
|
+
export const ArtifactCacheTagSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((tag) => tag.startsWith(ARTIFACT_CACHE_PREFIX) &&
|
|
12
|
+
Schema.is(Sha256HashSchema)(tag.slice(ARTIFACT_CACHE_PREFIX.length)), {
|
|
13
|
+
message: "Expected content-artifact followed by one canonical SHA-256 hash.",
|
|
14
|
+
})), Schema.brand("@NakafaAI/AksaraArtifactCacheTag"));
|
|
15
|
+
/** One exact content-family cache tag derived from the family contract. */
|
|
16
|
+
export const ContentFamilyCacheTagSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((tag) => tag.startsWith(FAMILY_CACHE_PREFIX) &&
|
|
17
|
+
Schema.is(ContentFamilySchema)(tag.slice(FAMILY_CACHE_PREFIX.length)), { message: "Expected one canonical content-family cache tag." })), Schema.brand("@NakafaAI/AksaraContentFamilyCacheTag"));
|
|
18
|
+
/** Checks one cache request carries no redundant exact artifact tags. */
|
|
19
|
+
function hasUniqueArtifactTags(tags) {
|
|
20
|
+
const artifacts = tags.slice(2);
|
|
21
|
+
return new Set(artifacts).size === artifacts.length;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Ordered cache tags shared by Aksara and Nakafa.
|
|
25
|
+
*
|
|
26
|
+
* Global and exact family tags come first; remaining tags name exact changed
|
|
27
|
+
* artifacts while keeping one invalidation request at or below 100 tags.
|
|
28
|
+
*/
|
|
29
|
+
export const ContentCacheTagsSchema = Schema.TupleWithRest(Schema.Tuple([
|
|
30
|
+
Schema.Literal(CONTENT_CACHE_GLOBAL_TAG),
|
|
31
|
+
ContentFamilyCacheTagSchema,
|
|
32
|
+
]), [ArtifactCacheTagSchema]).pipe(Schema.check(Schema.isMaxLength(MAX_CONTENT_CACHE_ARTIFACTS + 2)), Schema.check(Schema.makeFilter(hasUniqueArtifactTags, {
|
|
33
|
+
message: "Expected unique exact artifact cache tags.",
|
|
34
|
+
})));
|
|
35
|
+
/** One changed family plus its optional newly published immutable artifact. */
|
|
36
|
+
export const ContentCacheChangeSchema = Schema.Struct({
|
|
37
|
+
artifactHash: Schema.optional(Sha256HashSchema),
|
|
38
|
+
family: ContentFamilySchema,
|
|
39
|
+
});
|
|
40
|
+
/** Derives the canonical cache tag for one already-canonical artifact hash. */
|
|
41
|
+
export function makeArtifactCacheTag(hash) {
|
|
42
|
+
return ArtifactCacheTagSchema.make(`${ARTIFACT_CACHE_PREFIX}${hash}`);
|
|
43
|
+
}
|
|
44
|
+
/** Derives the canonical cache tag for one implemented content family. */
|
|
45
|
+
export function makeContentFamilyCacheTag(family) {
|
|
46
|
+
return ContentFamilyCacheTagSchema.make(`${FAMILY_CACHE_PREFIX}${family}`);
|
|
47
|
+
}
|
|
48
|
+
/** Checks the explicit family and ordered family cache tag cannot disagree. */
|
|
49
|
+
function hasCoherentFamily(input) {
|
|
50
|
+
return input.tags[1] === makeContentFamilyCacheTag(input.family);
|
|
51
|
+
}
|
|
52
|
+
/** One release-bound, family-exact cache invalidation request. */
|
|
53
|
+
export const ContentCacheRequestSchema = Schema.Struct({
|
|
54
|
+
family: ContentFamilySchema,
|
|
55
|
+
releaseId: ReleaseIdSchema,
|
|
56
|
+
tags: ContentCacheTagsSchema,
|
|
57
|
+
}).pipe(Schema.check(Schema.makeFilter(hasCoherentFamily, {
|
|
58
|
+
message: "Expected the cache family to match its ordered family tag.",
|
|
59
|
+
})));
|
|
60
|
+
/** Nakafa proof that one exact release-bound invalidation completed. */
|
|
61
|
+
export const ContentCacheReceiptSchema = Schema.Struct({
|
|
62
|
+
family: ContentFamilySchema,
|
|
63
|
+
releaseId: ReleaseIdSchema,
|
|
64
|
+
revalidated: Schema.Literal(true),
|
|
65
|
+
tags: ContentCacheTagsSchema,
|
|
66
|
+
}).pipe(Schema.check(Schema.makeFilter(hasCoherentFamily, {
|
|
67
|
+
message: "Expected the cache family to match its ordered family tag.",
|
|
68
|
+
})));
|
|
69
|
+
/** Builds one ordered invalidation request for one exact content family. */
|
|
70
|
+
export function makeContentCacheRequest(input) {
|
|
71
|
+
return ContentCacheRequestSchema.make({
|
|
72
|
+
family: input.family,
|
|
73
|
+
releaseId: input.releaseId,
|
|
74
|
+
tags: [
|
|
75
|
+
CONTENT_CACHE_GLOBAL_TAG,
|
|
76
|
+
makeContentFamilyCacheTag(input.family),
|
|
77
|
+
...input.artifactHashes.map(makeArtifactCacheTag),
|
|
78
|
+
],
|
|
79
|
+
});
|
|
80
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { type ContentKey, type PublicPath, Sha256HashSchema } from "#contracts/ids";
|
|
3
|
+
import { type AppLocale, type ArtifactLocale } from "#contracts/locale";
|
|
4
|
+
/** Published content families backed by real Aksara source registries. */
|
|
5
|
+
export declare const ContentFamilySchema: Schema.Literals<readonly ["article", "material", "page", "question"]>;
|
|
6
|
+
export type ContentFamily = typeof ContentFamilySchema.Type;
|
|
7
|
+
/** Exact authored person identity exposed by Nakafa content metadata. */
|
|
8
|
+
export declare const ContentAuthorSchema: Schema.Struct<{
|
|
9
|
+
readonly name: Schema.String;
|
|
10
|
+
}>;
|
|
11
|
+
export type ContentAuthor = typeof ContentAuthorSchema.Type;
|
|
12
|
+
/** Stable language-specific identity shared by artifacts and content heads. */
|
|
13
|
+
export interface ContentHeadIdentity {
|
|
14
|
+
readonly artifactLocale: ArtifactLocale;
|
|
15
|
+
readonly contentKey: ContentKey;
|
|
16
|
+
}
|
|
17
|
+
/** Builds the unambiguous key used for one language-specific content head. */
|
|
18
|
+
export declare function headIdentity(input: ContentHeadIdentity): string;
|
|
19
|
+
/** Builds the unambiguous key used for one application-localized route. */
|
|
20
|
+
export declare function routeIdentity(input: {
|
|
21
|
+
readonly appLocale: AppLocale;
|
|
22
|
+
readonly publicPath: PublicPath;
|
|
23
|
+
}): string;
|
|
24
|
+
/** Compares content heads using deterministic Unicode code-unit order. */
|
|
25
|
+
export declare function compareContentHeads(left: ContentHeadIdentity, right: ContentHeadIdentity): -1 | 0 | 1;
|
|
26
|
+
/** Compiler protocol implemented by this Aksara compiler release. */
|
|
27
|
+
export declare const AKSARA_COMPILER_VERSION = "0.1.0";
|
|
28
|
+
/** Official MDX compiler version used to produce function-body artifacts. */
|
|
29
|
+
export declare const MDX_COMPILER_VERSION = "3.1.1";
|
|
30
|
+
/** Authored source identity accepted before deterministic compilation. */
|
|
31
|
+
export declare const CompileDocumentSourceSchema: Schema.Struct<{
|
|
32
|
+
readonly artifactLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraArtifactLocale">;
|
|
33
|
+
readonly contentKey: Schema.brand<Schema.String, "@NakafaAI/AksaraContentKey">;
|
|
34
|
+
readonly rawMdx: Schema.String;
|
|
35
|
+
readonly rendererDomain: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
36
|
+
readonly sourcePath: Schema.brand<Schema.String, "@NakafaAI/AksaraCorpusSourcePath">;
|
|
37
|
+
}>;
|
|
38
|
+
export type CompileDocumentSource = typeof CompileDocumentSourceSchema.Type;
|
|
39
|
+
/** Validated request accepted by the trusted MDX compiler. */
|
|
40
|
+
export declare const CompileDocumentRequestSchema: Schema.Struct<{
|
|
41
|
+
readonly artifactLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraArtifactLocale">;
|
|
42
|
+
readonly contentKey: Schema.brand<Schema.String, "@NakafaAI/AksaraContentKey">;
|
|
43
|
+
readonly rawMdx: Schema.String;
|
|
44
|
+
readonly rendererDomain: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
45
|
+
readonly sourcePath: Schema.brand<Schema.String, "@NakafaAI/AksaraCorpusSourcePath">;
|
|
46
|
+
readonly rendererManifest: Schema.Struct<{
|
|
47
|
+
readonly base: Schema.Struct<{
|
|
48
|
+
authoringComponents: Schema.$Array<Schema.Struct<{
|
|
49
|
+
readonly name: Schema.String;
|
|
50
|
+
readonly version: Schema.Finite;
|
|
51
|
+
}>>;
|
|
52
|
+
supportedComponents: Schema.$Array<Schema.Struct<{
|
|
53
|
+
readonly name: Schema.String;
|
|
54
|
+
readonly version: Schema.Finite;
|
|
55
|
+
}>>;
|
|
56
|
+
}>;
|
|
57
|
+
readonly domains: Schema.$Array<Schema.Struct<{
|
|
58
|
+
readonly authoringComponents: Schema.$Array<Schema.Struct<{
|
|
59
|
+
readonly name: Schema.String;
|
|
60
|
+
readonly version: Schema.Finite;
|
|
61
|
+
}>>;
|
|
62
|
+
readonly name: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
63
|
+
readonly supportedComponents: Schema.$Array<Schema.Struct<{
|
|
64
|
+
readonly name: Schema.String;
|
|
65
|
+
readonly version: Schema.Finite;
|
|
66
|
+
}>>;
|
|
67
|
+
}>>;
|
|
68
|
+
readonly format: Schema.Literal<"nakafa-mdx-renderer-v1">;
|
|
69
|
+
readonly hash: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
70
|
+
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"]>>;
|
|
71
|
+
readonly rendererContractVersion: Schema.Literal<"1.0.0">;
|
|
72
|
+
}>;
|
|
73
|
+
}>;
|
|
74
|
+
export type CompileDocumentRequest = typeof CompileDocumentRequestSchema.Type;
|
|
75
|
+
/** Precompiled trusted payload stored and signed before server-only execution. */
|
|
76
|
+
export declare const CompiledContentPayloadSchema: Schema.Struct<{
|
|
77
|
+
readonly artifactLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraArtifactLocale">;
|
|
78
|
+
readonly byteLength: Schema.Finite;
|
|
79
|
+
readonly compiledCode: Schema.String;
|
|
80
|
+
readonly compilerConfigHash: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
81
|
+
readonly compilerVersion: Schema.Literal<"0.1.0">;
|
|
82
|
+
readonly contentKey: Schema.brand<Schema.String, "@NakafaAI/AksaraContentKey">;
|
|
83
|
+
readonly format: Schema.Literal<"mdx-function-body">;
|
|
84
|
+
readonly mdxCompilerVersion: Schema.Literal<"3.1.1">;
|
|
85
|
+
readonly plainText: Schema.String;
|
|
86
|
+
readonly rawMdx: Schema.String;
|
|
87
|
+
readonly rendererDomain: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
88
|
+
readonly requiredComponents: Schema.$Array<Schema.Struct<{
|
|
89
|
+
readonly name: Schema.String;
|
|
90
|
+
readonly version: Schema.Finite;
|
|
91
|
+
}>>;
|
|
92
|
+
readonly sourceHash: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
93
|
+
}>;
|
|
94
|
+
export type CompiledContentPayload = typeof CompiledContentPayloadSchema.Type;
|
|
95
|
+
/** Immutable compiled payload plus its asymmetric authenticity proof. */
|
|
96
|
+
export declare const SignedContentArtifactSchema: Schema.Struct<{
|
|
97
|
+
readonly artifactHash: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
98
|
+
readonly keyId: Schema.brand<Schema.String, "@NakafaAI/AksaraSigningKeyId">;
|
|
99
|
+
readonly payload: Schema.Struct<{
|
|
100
|
+
readonly artifactLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraArtifactLocale">;
|
|
101
|
+
readonly byteLength: Schema.Finite;
|
|
102
|
+
readonly compiledCode: Schema.String;
|
|
103
|
+
readonly compilerConfigHash: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
104
|
+
readonly compilerVersion: Schema.Literal<"0.1.0">;
|
|
105
|
+
readonly contentKey: Schema.brand<Schema.String, "@NakafaAI/AksaraContentKey">;
|
|
106
|
+
readonly format: Schema.Literal<"mdx-function-body">;
|
|
107
|
+
readonly mdxCompilerVersion: Schema.Literal<"3.1.1">;
|
|
108
|
+
readonly plainText: Schema.String;
|
|
109
|
+
readonly rawMdx: Schema.String;
|
|
110
|
+
readonly rendererDomain: Schema.Literals<readonly ["ai-ds", "biology", "chemistry", "mathematics", "physics", "politics", "site", "snbt-general", "snbt-math", "snbt-plain", "snbt-quant", "tka-math"]>;
|
|
111
|
+
readonly requiredComponents: Schema.$Array<Schema.Struct<{
|
|
112
|
+
readonly name: Schema.String;
|
|
113
|
+
readonly version: Schema.Finite;
|
|
114
|
+
}>>;
|
|
115
|
+
readonly sourceHash: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
116
|
+
}>;
|
|
117
|
+
readonly signature: Schema.brand<Schema.String, "@NakafaAI/AksaraEd25519Signature">;
|
|
118
|
+
}>;
|
|
119
|
+
export type SignedContentArtifact = typeof SignedContentArtifactSchema.Type;
|
|
120
|
+
/** Serializes a compiled payload with stable field and component order. */
|
|
121
|
+
export declare function canonicalizeCompiledContentPayload(payload: CompiledContentPayload): string;
|
|
122
|
+
/** Returns the domain-separated canonical bytes covered by Ed25519. */
|
|
123
|
+
export declare function canonicalizeContentArtifactSigningInput(artifactHash: typeof Sha256HashSchema.Type, payload: CompiledContentPayload): string;
|
|
124
|
+
/** Serializes a complete signed artifact with deterministic wire field order. */
|
|
125
|
+
export declare function canonicalizeSignedContentArtifact(artifact: SignedContentArtifact): string;
|
|
126
|
+
/** Decodes unknown compiler input without throwing parser exceptions. */
|
|
127
|
+
export declare const decodeCompileDocumentRequest: (input: unknown) => Effect.Effect<{
|
|
128
|
+
readonly artifactLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraArtifactLocale">;
|
|
129
|
+
readonly contentKey: string & import("effect/Brand").Brand<"@NakafaAI/AksaraContentKey">;
|
|
130
|
+
readonly rawMdx: string;
|
|
131
|
+
readonly rendererDomain: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math";
|
|
132
|
+
readonly sourcePath: string & import("effect/Brand").Brand<"@NakafaAI/AksaraCorpusSourcePath">;
|
|
133
|
+
readonly rendererManifest: {
|
|
134
|
+
readonly base: {
|
|
135
|
+
readonly authoringComponents: readonly {
|
|
136
|
+
readonly name: string;
|
|
137
|
+
readonly version: number;
|
|
138
|
+
}[];
|
|
139
|
+
readonly supportedComponents: readonly {
|
|
140
|
+
readonly name: string;
|
|
141
|
+
readonly version: number;
|
|
142
|
+
}[];
|
|
143
|
+
};
|
|
144
|
+
readonly domains: readonly {
|
|
145
|
+
readonly authoringComponents: readonly {
|
|
146
|
+
readonly name: string;
|
|
147
|
+
readonly version: number;
|
|
148
|
+
}[];
|
|
149
|
+
readonly name: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math";
|
|
150
|
+
readonly supportedComponents: readonly {
|
|
151
|
+
readonly name: string;
|
|
152
|
+
readonly version: number;
|
|
153
|
+
}[];
|
|
154
|
+
}[];
|
|
155
|
+
readonly format: "nakafa-mdx-renderer-v1";
|
|
156
|
+
readonly hash: string & import("effect/Brand").Brand<"@NakafaAI/AksaraSha256Hash">;
|
|
157
|
+
readonly publishedDomains: readonly ("ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math")[];
|
|
158
|
+
readonly rendererContractVersion: "1.0.0";
|
|
159
|
+
};
|
|
160
|
+
}, import("./errors.js").ContractDecodeError, never>;
|
|
161
|
+
/** Strictly decodes one authored source before a publication recompile. */
|
|
162
|
+
export declare const decodeCompileDocumentSource: (input: unknown) => Effect.Effect<{
|
|
163
|
+
readonly artifactLocale: ("de" | "en" | "id") & import("effect/Brand").Brand<"@NakafaAI/AksaraArtifactLocale">;
|
|
164
|
+
readonly contentKey: string & import("effect/Brand").Brand<"@NakafaAI/AksaraContentKey">;
|
|
165
|
+
readonly rawMdx: string;
|
|
166
|
+
readonly rendererDomain: "ai-ds" | "biology" | "chemistry" | "mathematics" | "physics" | "politics" | "site" | "snbt-general" | "snbt-math" | "snbt-plain" | "snbt-quant" | "tka-math";
|
|
167
|
+
readonly sourcePath: string & import("effect/Brand").Brand<"@NakafaAI/AksaraCorpusSourcePath">;
|
|
168
|
+
}, import("./errors.js").ContractDecodeError, never>;
|
package/dist/content.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { decodeContract } from "#contracts/decode";
|
|
3
|
+
import { ContentKeySchema, CorpusSourcePathSchema, Ed25519SignatureSchema, Sha256HashSchema, SigningKeyIdSchema, } from "#contracts/ids";
|
|
4
|
+
import { ArtifactLocaleSchema, } from "#contracts/locale";
|
|
5
|
+
import { CompiledContentRequirementsSchema } from "#contracts/renderer/component";
|
|
6
|
+
import { RendererManifestEnvelopeSchema } from "#contracts/renderer/contract";
|
|
7
|
+
import { RendererDomainSchema } from "#contracts/renderer/domain";
|
|
8
|
+
import { compareCodeUnits } from "#contracts/text/order";
|
|
9
|
+
/** Published content families backed by real Aksara source registries. */
|
|
10
|
+
export const ContentFamilySchema = Schema.Literals([
|
|
11
|
+
"article",
|
|
12
|
+
"material",
|
|
13
|
+
"page",
|
|
14
|
+
"question",
|
|
15
|
+
]);
|
|
16
|
+
/** Exact authored person identity exposed by Nakafa content metadata. */
|
|
17
|
+
export const ContentAuthorSchema = Schema.Struct({ name: Schema.String });
|
|
18
|
+
/** Builds the unambiguous key used for one language-specific content head. */
|
|
19
|
+
export function headIdentity(input) {
|
|
20
|
+
return `${input.contentKey}\0${input.artifactLocale}`;
|
|
21
|
+
}
|
|
22
|
+
/** Builds the unambiguous key used for one application-localized route. */
|
|
23
|
+
export function routeIdentity(input) {
|
|
24
|
+
return `${input.appLocale}\0${input.publicPath}`;
|
|
25
|
+
}
|
|
26
|
+
/** Compares content heads using deterministic Unicode code-unit order. */
|
|
27
|
+
export function compareContentHeads(left, right) {
|
|
28
|
+
const contentKeyOrder = compareCodeUnits(left.contentKey, right.contentKey);
|
|
29
|
+
return (contentKeyOrder ||
|
|
30
|
+
compareCodeUnits(left.artifactLocale, right.artifactLocale));
|
|
31
|
+
}
|
|
32
|
+
/** Compiler protocol implemented by this Aksara compiler release. */
|
|
33
|
+
export const AKSARA_COMPILER_VERSION = "0.1.0";
|
|
34
|
+
/** Official MDX compiler version used to produce function-body artifacts. */
|
|
35
|
+
export const MDX_COMPILER_VERSION = "3.1.1";
|
|
36
|
+
/** Authored source identity accepted before deterministic compilation. */
|
|
37
|
+
export const CompileDocumentSourceSchema = Schema.Struct({
|
|
38
|
+
artifactLocale: ArtifactLocaleSchema,
|
|
39
|
+
contentKey: ContentKeySchema,
|
|
40
|
+
rawMdx: Schema.String,
|
|
41
|
+
rendererDomain: RendererDomainSchema,
|
|
42
|
+
sourcePath: CorpusSourcePathSchema,
|
|
43
|
+
});
|
|
44
|
+
/** Validated request accepted by the trusted MDX compiler. */
|
|
45
|
+
export const CompileDocumentRequestSchema = Schema.Struct({
|
|
46
|
+
...CompileDocumentSourceSchema.fields,
|
|
47
|
+
rendererManifest: RendererManifestEnvelopeSchema,
|
|
48
|
+
}).pipe(Schema.check(Schema.makeFilter((request) => request.rendererManifest.domains.some(({ name }) => name === request.rendererDomain), {
|
|
49
|
+
message: "Expected the selected renderer domain to have a capability.",
|
|
50
|
+
})));
|
|
51
|
+
/** Precompiled trusted payload stored and signed before server-only execution. */
|
|
52
|
+
export const CompiledContentPayloadSchema = Schema.Struct({
|
|
53
|
+
artifactLocale: ArtifactLocaleSchema,
|
|
54
|
+
byteLength: Schema.Finite.pipe(Schema.check(Schema.isInt()), Schema.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
55
|
+
compiledCode: Schema.String,
|
|
56
|
+
compilerConfigHash: Sha256HashSchema,
|
|
57
|
+
compilerVersion: Schema.Literal(AKSARA_COMPILER_VERSION),
|
|
58
|
+
contentKey: ContentKeySchema,
|
|
59
|
+
format: Schema.Literal("mdx-function-body"),
|
|
60
|
+
mdxCompilerVersion: Schema.Literal(MDX_COMPILER_VERSION),
|
|
61
|
+
plainText: Schema.String,
|
|
62
|
+
rawMdx: Schema.String,
|
|
63
|
+
rendererDomain: RendererDomainSchema,
|
|
64
|
+
requiredComponents: CompiledContentRequirementsSchema,
|
|
65
|
+
sourceHash: Sha256HashSchema,
|
|
66
|
+
});
|
|
67
|
+
/** Immutable compiled payload plus its asymmetric authenticity proof. */
|
|
68
|
+
export const SignedContentArtifactSchema = Schema.Struct({
|
|
69
|
+
artifactHash: Sha256HashSchema,
|
|
70
|
+
keyId: SigningKeyIdSchema,
|
|
71
|
+
payload: CompiledContentPayloadSchema,
|
|
72
|
+
signature: Ed25519SignatureSchema,
|
|
73
|
+
});
|
|
74
|
+
const CONTENT_ARTIFACT_SIGNATURE_DOMAIN = "nakafa.aksara.content-artifact";
|
|
75
|
+
/** Serializes a compiled payload with stable field and component order. */
|
|
76
|
+
export function canonicalizeCompiledContentPayload(payload) {
|
|
77
|
+
return JSON.stringify({
|
|
78
|
+
artifactLocale: payload.artifactLocale,
|
|
79
|
+
byteLength: payload.byteLength,
|
|
80
|
+
compiledCode: payload.compiledCode,
|
|
81
|
+
compilerConfigHash: payload.compilerConfigHash,
|
|
82
|
+
compilerVersion: payload.compilerVersion,
|
|
83
|
+
contentKey: payload.contentKey,
|
|
84
|
+
format: payload.format,
|
|
85
|
+
mdxCompilerVersion: payload.mdxCompilerVersion,
|
|
86
|
+
plainText: payload.plainText,
|
|
87
|
+
rawMdx: payload.rawMdx,
|
|
88
|
+
rendererDomain: payload.rendererDomain,
|
|
89
|
+
requiredComponents: payload.requiredComponents.map(({ name, version }) => ({
|
|
90
|
+
name,
|
|
91
|
+
version,
|
|
92
|
+
})),
|
|
93
|
+
sourceHash: payload.sourceHash,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/** Returns the domain-separated canonical bytes covered by Ed25519. */
|
|
97
|
+
export function canonicalizeContentArtifactSigningInput(artifactHash, payload) {
|
|
98
|
+
return `${CONTENT_ARTIFACT_SIGNATURE_DOMAIN}\n${artifactHash}\n${canonicalizeCompiledContentPayload(payload)}`;
|
|
99
|
+
}
|
|
100
|
+
/** Serializes a complete signed artifact with deterministic wire field order. */
|
|
101
|
+
export function canonicalizeSignedContentArtifact(artifact) {
|
|
102
|
+
return `{"artifactHash":${JSON.stringify(artifact.artifactHash)},"keyId":${JSON.stringify(artifact.keyId)},"payload":${canonicalizeCompiledContentPayload(artifact.payload)},"signature":${JSON.stringify(artifact.signature)}}`;
|
|
103
|
+
}
|
|
104
|
+
/** Decodes unknown compiler input without throwing parser exceptions. */
|
|
105
|
+
export const decodeCompileDocumentRequest = Effect.fn("AksaraContracts.decodeCompileDocumentRequest")((input) => decodeContract(CompileDocumentRequestSchema, "CompileDocumentRequest", input));
|
|
106
|
+
/** Strictly decodes one authored source before a publication recompile. */
|
|
107
|
+
export const decodeCompileDocumentSource = Effect.fn("AksaraContracts.decodeCompileDocumentSource")((input) => decodeContract(CompileDocumentSourceSchema, "CompileDocumentSource", input));
|
package/dist/country.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
const COUNTRY_CODE_PATTERN = /^[A-Z]{2}$/u;
|
|
3
|
+
/** ISO 3166-1 alpha-2 code shared by country-owned content domains. */
|
|
4
|
+
export const CountryCodeSchema = Schema.String.pipe(Schema.check(Schema.isPattern(COUNTRY_CODE_PATTERN, {
|
|
5
|
+
description: "Uppercase ISO 3166-1 alpha-2 country code.",
|
|
6
|
+
identifier: "CountryCode",
|
|
7
|
+
message: "Invalid country code.",
|
|
8
|
+
})));
|
package/dist/date.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** Exact source-authored calendar date shared by content projections. */
|
|
3
|
+
export declare const DateOnlySchema: Schema.String;
|
|
4
|
+
export type DateOnly = typeof DateOnlySchema.Type;
|
|
5
|
+
/**
|
|
6
|
+
* Public authored dates backed by signed activation history.
|
|
7
|
+
* Publication is locale-specific; modification records only a later meaningful
|
|
8
|
+
* content activation and is never synthesized from a runtime clock.
|
|
9
|
+
*/
|
|
10
|
+
export declare const PublicationDatesSchema: Schema.Struct<{
|
|
11
|
+
dateModified: Schema.optionalKey<Schema.String>;
|
|
12
|
+
datePublished: Schema.String;
|
|
13
|
+
}>;
|
|
14
|
+
export type PublicationDates = typeof PublicationDatesSchema.Type;
|
|
15
|
+
/**
|
|
16
|
+
* Adds exact publication dates and their chronological invariant to metadata.
|
|
17
|
+
*
|
|
18
|
+
* The date fields and their check remain one contract so callers cannot copy
|
|
19
|
+
* the shape without also enforcing the public ordering rule.
|
|
20
|
+
*/
|
|
21
|
+
export declare function withPublicationDates<const Fields extends Schema.Struct.Fields>(fields: Fields): Schema.Struct<Readonly<Fields & {
|
|
22
|
+
dateModified: Schema.optionalKey<Schema.String>;
|
|
23
|
+
datePublished: Schema.String;
|
|
24
|
+
}> extends infer T ? { [K in keyof T]: T[K]; } : never>;
|
package/dist/date.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
const DATE_ONLY_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/u;
|
|
3
|
+
/** Checks a source-authored date against the real ISO calendar. */
|
|
4
|
+
function isDateOnly(value) {
|
|
5
|
+
if (!DATE_ONLY_PATTERN.test(value)) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
const year = Number.parseInt(value.slice(0, 4), 10);
|
|
9
|
+
const month = Number.parseInt(value.slice(5, 7), 10);
|
|
10
|
+
const day = Number.parseInt(value.slice(8, 10), 10);
|
|
11
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
12
|
+
return (date.getUTCFullYear() === year &&
|
|
13
|
+
date.getUTCMonth() === month - 1 &&
|
|
14
|
+
date.getUTCDate() === day);
|
|
15
|
+
}
|
|
16
|
+
/** Exact source-authored calendar date shared by content projections. */
|
|
17
|
+
export const DateOnlySchema = Schema.String.pipe(Schema.check(Schema.makeFilter(isDateOnly)));
|
|
18
|
+
const PUBLICATION_DATE_ORDER_MESSAGE = "Expected dateModified to be later than datePublished.";
|
|
19
|
+
const PublicationDateFields = {
|
|
20
|
+
dateModified: Schema.optionalKey(DateOnlySchema),
|
|
21
|
+
datePublished: DateOnlySchema,
|
|
22
|
+
};
|
|
23
|
+
const PublicationDatesStruct = Schema.Struct(PublicationDateFields).annotate({
|
|
24
|
+
parseOptions: { onExcessProperty: "error" },
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Public authored dates backed by signed activation history.
|
|
28
|
+
* Publication is locale-specific; modification records only a later meaningful
|
|
29
|
+
* content activation and is never synthesized from a runtime clock.
|
|
30
|
+
*/
|
|
31
|
+
export const PublicationDatesSchema = PublicationDatesStruct.pipe(Schema.check(Schema.makeFilter((input) => input.dateModified === undefined ||
|
|
32
|
+
input.dateModified > input.datePublished, { message: PUBLICATION_DATE_ORDER_MESSAGE })), Schema.annotate({ parseOptions: { onExcessProperty: "error" } }));
|
|
33
|
+
/**
|
|
34
|
+
* Adds exact publication dates and their chronological invariant to metadata.
|
|
35
|
+
*
|
|
36
|
+
* The date fields and their check remain one contract so callers cannot copy
|
|
37
|
+
* the shape without also enforcing the public ordering rule.
|
|
38
|
+
*/
|
|
39
|
+
export function withPublicationDates(fields) {
|
|
40
|
+
return PublicationDatesSchema.mapFields((dateFields) => ({ ...fields, ...dateFields }),
|
|
41
|
+
// Adding fields cannot invalidate the date check because the owning date
|
|
42
|
+
// fields are preserved unchanged and always win key collisions.
|
|
43
|
+
{ unsafePreserveChecks: true }).annotate({ parseOptions: { onExcessProperty: "error" } });
|
|
44
|
+
}
|