@agentxm/registry-protocol 0.28.4-bootstrap.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 +110 -0
- package/README.md +13 -0
- package/dist/src/unstable/content/agent-skills-standard.d.ts +17 -0
- package/dist/src/unstable/content/agent-skills-standard.js +24 -0
- package/dist/src/unstable/content/frontmatter.d.ts +52 -0
- package/dist/src/unstable/content/frontmatter.js +115 -0
- package/dist/src/unstable/content/index.d.ts +11 -0
- package/dist/src/unstable/content/index.js +11 -0
- package/dist/src/unstable/content/skill-content.d.ts +43 -0
- package/dist/src/unstable/content/skill-content.js +184 -0
- package/dist/src/unstable/content/skill-types.d.ts +22 -0
- package/dist/src/unstable/content/skill-types.js +9 -0
- package/dist/src/unstable/content/subagent-content.d.ts +58 -0
- package/dist/src/unstable/content/subagent-content.js +101 -0
- package/dist/src/unstable/knowledge/index.d.ts +8 -0
- package/dist/src/unstable/knowledge/index.js +8 -0
- package/dist/src/unstable/knowledge/knowledge-search.d.ts +32 -0
- package/dist/src/unstable/knowledge/knowledge-search.js +147 -0
- package/dist/src/unstable/knowledge/okf.d.ts +86 -0
- package/dist/src/unstable/knowledge/okf.js +1090 -0
- package/dist/src/unstable/lint/catalog/hook/decision-portability.d.ts +4 -0
- package/dist/src/unstable/lint/catalog/hook/decision-portability.js +40 -0
- package/dist/src/unstable/lint/catalog/hook/entrypoint-exists.d.ts +4 -0
- package/dist/src/unstable/lint/catalog/hook/entrypoint-exists.js +39 -0
- package/dist/src/unstable/lint/catalog/hook/envelope.d.ts +6 -0
- package/dist/src/unstable/lint/catalog/hook/envelope.js +15 -0
- package/dist/src/unstable/lint/catalog/hook/matcher-raw-portability.d.ts +4 -0
- package/dist/src/unstable/lint/catalog/hook/matcher-raw-portability.js +51 -0
- package/dist/src/unstable/lint/catalog/hook.d.ts +4 -0
- package/dist/src/unstable/lint/catalog/hook.js +17 -0
- package/dist/src/unstable/lint/catalog/knowledge/diagnostics.d.ts +128 -0
- package/dist/src/unstable/lint/catalog/knowledge/diagnostics.js +78 -0
- package/dist/src/unstable/lint/catalog/knowledge/envelope.d.ts +6 -0
- package/dist/src/unstable/lint/catalog/knowledge/envelope.js +15 -0
- package/dist/src/unstable/lint/catalog/knowledge.d.ts +5 -0
- package/dist/src/unstable/lint/catalog/knowledge.js +11 -0
- package/dist/src/unstable/lint/catalog/mcp-server/envelope.d.ts +6 -0
- package/dist/src/unstable/lint/catalog/mcp-server/envelope.js +15 -0
- package/dist/src/unstable/lint/catalog/mcp-server.d.ts +4 -0
- package/dist/src/unstable/lint/catalog/mcp-server.js +6 -0
- package/dist/src/unstable/lint/catalog/pack/manifest-keys-recognized.d.ts +28 -0
- package/dist/src/unstable/lint/catalog/pack/manifest-keys-recognized.js +38 -0
- package/dist/src/unstable/lint/catalog/pack/manifest-present.d.ts +17 -0
- package/dist/src/unstable/lint/catalog/pack/manifest-present.js +24 -0
- package/dist/src/unstable/lint/catalog/pack/manifest-schema-valid.d.ts +25 -0
- package/dist/src/unstable/lint/catalog/pack/manifest-schema-valid.js +33 -0
- package/dist/src/unstable/lint/catalog/pack-accessor/contexts.d.ts +51 -0
- package/dist/src/unstable/lint/catalog/pack-accessor/contexts.js +45 -0
- package/dist/src/unstable/lint/catalog/pack-accessor/vft.d.ts +60 -0
- package/dist/src/unstable/lint/catalog/pack-accessor/vft.js +85 -0
- package/dist/src/unstable/lint/catalog/pack.d.ts +37 -0
- package/dist/src/unstable/lint/catalog/pack.js +47 -0
- package/dist/src/unstable/lint/catalog/rule/envelope.d.ts +6 -0
- package/dist/src/unstable/lint/catalog/rule/envelope.js +15 -0
- package/dist/src/unstable/lint/catalog/rule.d.ts +4 -0
- package/dist/src/unstable/lint/catalog/rule.js +6 -0
- package/dist/src/unstable/lint/catalog/shared/envelope-rules.d.ts +93 -0
- package/dist/src/unstable/lint/catalog/shared/envelope-rules.js +89 -0
- package/dist/src/unstable/lint/catalog/shared/manifest-json.d.ts +18 -0
- package/dist/src/unstable/lint/catalog/shared/manifest-json.js +28 -0
- package/dist/src/unstable/lint/catalog/shared/manifest-present.d.ts +25 -0
- package/dist/src/unstable/lint/catalog/shared/manifest-present.js +37 -0
- package/dist/src/unstable/lint/catalog/shared/recommended-packs-rules.d.ts +70 -0
- package/dist/src/unstable/lint/catalog/shared/recommended-packs-rules.js +139 -0
- package/dist/src/unstable/lint/catalog/shared/schema-rule.d.ts +58 -0
- package/dist/src/unstable/lint/catalog/shared/schema-rule.js +103 -0
- package/dist/src/unstable/lint/catalog/skill/frontmatter-parseable.d.ts +31 -0
- package/dist/src/unstable/lint/catalog/skill/frontmatter-parseable.js +148 -0
- package/dist/src/unstable/lint/catalog/skill/frontmatter-standard-valid.d.ts +13 -0
- package/dist/src/unstable/lint/catalog/skill/frontmatter-standard-valid.js +61 -0
- package/dist/src/unstable/lint/catalog/skill/manifest-keys-recognized.d.ts +26 -0
- package/dist/src/unstable/lint/catalog/skill/manifest-keys-recognized.js +41 -0
- package/dist/src/unstable/lint/catalog/skill/manifest-present.d.ts +23 -0
- package/dist/src/unstable/lint/catalog/skill/manifest-present.js +32 -0
- package/dist/src/unstable/lint/catalog/skill/manifest-schema-valid.d.ts +21 -0
- package/dist/src/unstable/lint/catalog/skill/manifest-schema-valid.js +36 -0
- package/dist/src/unstable/lint/catalog/skill/recommended-packs-valid.d.ts +8 -0
- package/dist/src/unstable/lint/catalog/skill/recommended-packs-valid.js +12 -0
- package/dist/src/unstable/lint/catalog/skill/skill-md-present.d.ts +17 -0
- package/dist/src/unstable/lint/catalog/skill/skill-md-present.js +37 -0
- package/dist/src/unstable/lint/catalog/skill/standalone-declaration-valid.d.ts +8 -0
- package/dist/src/unstable/lint/catalog/skill/standalone-declaration-valid.js +12 -0
- package/dist/src/unstable/lint/catalog/skill-accessor/contexts.d.ts +61 -0
- package/dist/src/unstable/lint/catalog/skill-accessor/contexts.js +55 -0
- package/dist/src/unstable/lint/catalog/skill-accessor/vft.d.ts +77 -0
- package/dist/src/unstable/lint/catalog/skill-accessor/vft.js +135 -0
- package/dist/src/unstable/lint/catalog/skill.d.ts +44 -0
- package/dist/src/unstable/lint/catalog/skill.js +64 -0
- package/dist/src/unstable/lint/catalog/subagent/envelope.d.ts +6 -0
- package/dist/src/unstable/lint/catalog/subagent/envelope.js +15 -0
- package/dist/src/unstable/lint/catalog/subagent.d.ts +4 -0
- package/dist/src/unstable/lint/catalog/subagent.js +6 -0
- package/dist/src/unstable/lint/compose-path.d.ts +28 -0
- package/dist/src/unstable/lint/compose-path.js +64 -0
- package/dist/src/unstable/lint/config.d.ts +103 -0
- package/dist/src/unstable/lint/config.js +140 -0
- package/dist/src/unstable/lint/context.d.ts +246 -0
- package/dist/src/unstable/lint/context.js +21 -0
- package/dist/src/unstable/lint/describe-document.d.ts +31 -0
- package/dist/src/unstable/lint/describe-document.js +50 -0
- package/dist/src/unstable/lint/evaluate.d.ts +47 -0
- package/dist/src/unstable/lint/evaluate.js +82 -0
- package/dist/src/unstable/lint/issues-to-findings.d.ts +35 -0
- package/dist/src/unstable/lint/issues-to-findings.js +149 -0
- package/dist/src/unstable/lint/publish.d.ts +49 -0
- package/dist/src/unstable/lint/publish.js +86 -0
- package/dist/src/unstable/lint/rule.d.ts +98 -0
- package/dist/src/unstable/lint/rule.js +18 -0
- package/dist/src/unstable/publish/archive-guardrails.d.ts +39 -0
- package/dist/src/unstable/publish/archive-guardrails.js +250 -0
- package/dist/src/unstable/publish/filtered-package-validation.d.ts +24 -0
- package/dist/src/unstable/publish/filtered-package-validation.js +117 -0
- package/dist/src/unstable/publish/index.d.ts +12 -0
- package/dist/src/unstable/publish/index.js +12 -0
- package/dist/src/unstable/publish/ingest-limits.d.ts +25 -0
- package/dist/src/unstable/publish/ingest-limits.js +41 -0
- package/dist/src/unstable/publish/input-normalization.d.ts +40 -0
- package/dist/src/unstable/publish/input-normalization.js +125 -0
- package/dist/src/unstable/publish/manifest-policy.d.ts +611 -0
- package/dist/src/unstable/publish/manifest-policy.js +196 -0
- package/dist/src/unstable/publish/test-zip-helpers.d.ts +13 -0
- package/dist/src/unstable/publish/test-zip-helpers.js +117 -0
- package/dist/src/unstable/publish/visibility.d.ts +161 -0
- package/dist/src/unstable/publish/visibility.js +124 -0
- package/dist/src/unstable/registry/discover-schema.d.ts +68 -0
- package/dist/src/unstable/registry/discover-schema.js +35 -0
- package/dist/src/unstable/registry/index.d.ts +9 -0
- package/dist/src/unstable/registry/index.js +9 -0
- package/dist/src/unstable/registry/publication-set.d.ts +303 -0
- package/dist/src/unstable/registry/publication-set.js +507 -0
- package/dist/src/unstable/registry/release-age-policy.d.ts +57 -0
- package/dist/src/unstable/registry/release-age-policy.js +117 -0
- package/dist/src/unstable/registry/schema.d.ts +220 -0
- package/dist/src/unstable/registry/schema.js +114 -0
- package/dist/src/unstable/suggested-action.d.ts +19 -0
- package/dist/src/unstable/suggested-action.js +42 -0
- package/package.json +214 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as Data from "effect/Data";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Option from "effect/Option";
|
|
4
|
+
import { parseFrontmatterEffect } from "../content/frontmatter.js";
|
|
5
|
+
import { inspectKnowledgeEntries } from "../knowledge/okf.js";
|
|
6
|
+
import { parseSkillMd } from "../content/skill-content.js";
|
|
7
|
+
import { parseSubagentMd } from "../content/subagent-content.js";
|
|
8
|
+
/** A type-specific package invariant failed against the filtered archive. */
|
|
9
|
+
export class FilteredPackageError extends Data.TaggedError("FilteredPackageError") {
|
|
10
|
+
}
|
|
11
|
+
const rawField = (raw, field) => typeof raw === "object" && raw !== null && !Array.isArray(raw)
|
|
12
|
+
? Reflect.get(raw, field)
|
|
13
|
+
: undefined;
|
|
14
|
+
const safeArchivePath = (value) => value.length > 0 &&
|
|
15
|
+
!value.startsWith("/") &&
|
|
16
|
+
!value.includes("\\") &&
|
|
17
|
+
!value.split("/").some((segment) => segment === "" || segment === "." || segment === "..");
|
|
18
|
+
const requireEntry = (entries, path) => {
|
|
19
|
+
const found = entries.find((entry) => entry.fileName === path);
|
|
20
|
+
return found === undefined
|
|
21
|
+
? Effect.fail(new FilteredPackageError({
|
|
22
|
+
code: "required_file_missing",
|
|
23
|
+
detail: `Filtered ${path} is required by this package type.`,
|
|
24
|
+
path,
|
|
25
|
+
}))
|
|
26
|
+
: Effect.succeed(found);
|
|
27
|
+
};
|
|
28
|
+
const readText = (args, path) => Effect.gen(function* () {
|
|
29
|
+
yield* requireEntry(args.entries, path);
|
|
30
|
+
const bytes = yield* args.readEntry(path).pipe(Effect.mapError(() => new FilteredPackageError({
|
|
31
|
+
code: "content_invalid",
|
|
32
|
+
detail: `Could not read filtered package file "${path}".`,
|
|
33
|
+
path,
|
|
34
|
+
})));
|
|
35
|
+
return new TextDecoder().decode(bytes);
|
|
36
|
+
});
|
|
37
|
+
/** Validate the complete type-specific package after Registry-only filtering. */
|
|
38
|
+
export const validateFilteredPackage = (args) => Effect.gen(function* () {
|
|
39
|
+
const name = args.manifest.identity.name;
|
|
40
|
+
switch (args.type) {
|
|
41
|
+
case "skill": {
|
|
42
|
+
const path = "src/SKILL.md";
|
|
43
|
+
const content = yield* readText(args, path);
|
|
44
|
+
if (Option.isNone(parseSkillMd(content, name))) {
|
|
45
|
+
return yield* new FilteredPackageError({
|
|
46
|
+
code: "content_invalid",
|
|
47
|
+
detail: `Filtered "${path}" must contain valid Agent Skill frontmatter whose name is "${name}".`,
|
|
48
|
+
path,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
case "subagent": {
|
|
54
|
+
const path = `src/${name}.md`;
|
|
55
|
+
const content = yield* readText(args, path);
|
|
56
|
+
yield* parseSubagentMd(content, name).pipe(Effect.mapError(() => new FilteredPackageError({
|
|
57
|
+
code: "content_invalid",
|
|
58
|
+
detail: `Filtered "${path}" must contain valid subagent frontmatter whose name is "${name}".`,
|
|
59
|
+
path,
|
|
60
|
+
})));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
case "rule": {
|
|
64
|
+
const path = "src/RULE.md";
|
|
65
|
+
const content = yield* readText(args, path);
|
|
66
|
+
yield* parseFrontmatterEffect(content).pipe(Effect.mapError(() => new FilteredPackageError({
|
|
67
|
+
code: "content_invalid",
|
|
68
|
+
detail: `Filtered "${path}" contains invalid frontmatter.`,
|
|
69
|
+
path,
|
|
70
|
+
})));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
case "hook": {
|
|
74
|
+
const entrypoint = rawField(args.manifest.raw, "entrypoint");
|
|
75
|
+
if (typeof entrypoint !== "string" || !safeArchivePath(entrypoint)) {
|
|
76
|
+
return yield* new FilteredPackageError({
|
|
77
|
+
code: "reference_invalid",
|
|
78
|
+
detail: "Hook entrypoint must be a safe package-relative file path.",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
yield* requireEntry(args.entries, entrypoint);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
case "knowledge": {
|
|
85
|
+
if (rawField(args.manifest.raw, "bundleRoot") !== "src") {
|
|
86
|
+
return yield* new FilteredPackageError({
|
|
87
|
+
code: "reference_invalid",
|
|
88
|
+
detail: "Knowledge bundleRoot must resolve to the filtered src directory.",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
yield* readText(args, "src/index.md");
|
|
92
|
+
const sourcePrefix = "src/";
|
|
93
|
+
const knowledgeEntries = args.entries
|
|
94
|
+
.filter((entry) => entry.fileName.startsWith(sourcePrefix))
|
|
95
|
+
.map((entry) => ({
|
|
96
|
+
relativePath: entry.fileName.slice(sourcePrefix.length),
|
|
97
|
+
type: "File",
|
|
98
|
+
size: BigInt(entry.uncompressedSize),
|
|
99
|
+
}));
|
|
100
|
+
const inspection = yield* inspectKnowledgeEntries(knowledgeEntries, (relativePath) => readText(args, `${sourcePrefix}${relativePath}`));
|
|
101
|
+
const errors = inspection.diagnostics.filter((diagnostic) => diagnostic.severity === "error");
|
|
102
|
+
if (errors.length > 0) {
|
|
103
|
+
return yield* new FilteredPackageError({
|
|
104
|
+
code: "content_invalid",
|
|
105
|
+
detail: `Filtered Knowledge bundle is invalid: ${errors
|
|
106
|
+
.map((diagnostic) => `${diagnostic.relativePath}: ${diagnostic.message}`)
|
|
107
|
+
.join("; ")}`,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
case "mcp-server":
|
|
113
|
+
case "pack":
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=filtered-package-validation.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Area barrel for the package public surface.
|
|
3
|
+
*
|
|
4
|
+
* @experimental This API is unstable and may change without notice.
|
|
5
|
+
*/
|
|
6
|
+
export { ArchiveGuardrailError, type ArchiveGuardrailLimits, type ZipEntry, checkForbiddenSourceEntries, validateArchive, } from "./archive-guardrails.js";
|
|
7
|
+
export { FilteredPackageError, type ValidateFilteredPackageArgs, validateFilteredPackage, } from "./filtered-package-validation.js";
|
|
8
|
+
export { IngestLimitError, IngestUnsupportedContentTypeError, REGISTRY_PUBLISH_MAX_ARCHIVE_BYTES, REGISTRY_PUBLISH_MAX_REQUEST_BYTES, enforceArchiveContentType, enforceArchiveSizeLimit, enforceRequestSizeLimit, } from "./ingest-limits.js";
|
|
9
|
+
export { type NormalizePublishInputArgs, type PublishArchiveInput, type PublishInput, normalizePublishInput, } from "./input-normalization.js";
|
|
10
|
+
export { type DeclaredPublishIdentity, ManifestError, type ManifestIdentity, ManifestIdentitySchema, type ResolvedManifest, manifestFilenameForType, validateDeclaredManifestAlignment, } from "./manifest-policy.js";
|
|
11
|
+
export { type PublishVisibility, PublishVisibilitySchema, type ResolveVisibilityIntentArgs, type VisibilityActual, VisibilityActualSchema, type VisibilityComparison, VisibilityComparisonSchema, type VisibilityEvaluation, type VisibilityEvaluationResult, VisibilityEvaluationResultSchema, VisibilityEvaluationSchema, type VisibilityEvaluationUnavailable, VisibilityEvaluationUnavailableSchema, type VisibilityFinding, type VisibilityFindingCode, VisibilityFindingCodeSchema, VisibilityFindingSchema, type VisibilityFingerprint, VisibilityFingerprintSchema, type VisibilityIntent, VisibilityIntentSchema, type VisibilityIntentSource, type VisibilityMutationAuthority, VisibilityMutationAuthoritySchema, type VisibilityMutationRequest, VisibilityMutationRequestSchema, type VisibilityMutationResult, VisibilityMutationResultSchema, type VisibilityRevision, VisibilityRevisionSchema, resolveVisibilityIntent, } from "./visibility.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Area barrel for the package public surface.
|
|
3
|
+
*
|
|
4
|
+
* @experimental This API is unstable and may change without notice.
|
|
5
|
+
*/
|
|
6
|
+
export { ArchiveGuardrailError, checkForbiddenSourceEntries, validateArchive, } from "./archive-guardrails.js";
|
|
7
|
+
export { FilteredPackageError, validateFilteredPackage, } from "./filtered-package-validation.js";
|
|
8
|
+
export { IngestLimitError, IngestUnsupportedContentTypeError, REGISTRY_PUBLISH_MAX_ARCHIVE_BYTES, REGISTRY_PUBLISH_MAX_REQUEST_BYTES, enforceArchiveContentType, enforceArchiveSizeLimit, enforceRequestSizeLimit, } from "./ingest-limits.js";
|
|
9
|
+
export { normalizePublishInput, } from "./input-normalization.js";
|
|
10
|
+
export { ManifestError, ManifestIdentitySchema, manifestFilenameForType, validateDeclaredManifestAlignment, } from "./manifest-policy.js";
|
|
11
|
+
export { PublishVisibilitySchema, VisibilityActualSchema, VisibilityComparisonSchema, VisibilityEvaluationResultSchema, VisibilityEvaluationSchema, VisibilityEvaluationUnavailableSchema, VisibilityFindingCodeSchema, VisibilityFindingSchema, VisibilityFingerprintSchema, VisibilityIntentSchema, VisibilityMutationAuthoritySchema, VisibilityMutationRequestSchema, VisibilityMutationResultSchema, VisibilityRevisionSchema, resolveVisibilityIntent, } from "./visibility.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as Result from "effect/Result";
|
|
2
|
+
export declare const REGISTRY_PUBLISH_MAX_REQUEST_BYTES: number;
|
|
3
|
+
export declare const REGISTRY_PUBLISH_MAX_ARCHIVE_BYTES: number;
|
|
4
|
+
declare const IngestLimitError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
5
|
+
readonly _tag: "IngestLimitError";
|
|
6
|
+
} & Readonly<A>;
|
|
7
|
+
export declare class IngestLimitError extends IngestLimitError_base<{
|
|
8
|
+
readonly code: "ingest_request_too_large" | "ingest_archive_too_large" | "ingest_decompression_limit";
|
|
9
|
+
readonly detail: string;
|
|
10
|
+
readonly limit?: number;
|
|
11
|
+
readonly actual?: number;
|
|
12
|
+
}> {
|
|
13
|
+
}
|
|
14
|
+
declare const IngestUnsupportedContentTypeError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
15
|
+
readonly _tag: "IngestUnsupportedContentTypeError";
|
|
16
|
+
} & Readonly<A>;
|
|
17
|
+
export declare class IngestUnsupportedContentTypeError extends IngestUnsupportedContentTypeError_base<{
|
|
18
|
+
readonly detail: string;
|
|
19
|
+
}> {
|
|
20
|
+
}
|
|
21
|
+
export declare const enforceRequestSizeLimit: (contentLength: number | undefined, maxBytes?: number) => Result.Result<void, IngestLimitError>;
|
|
22
|
+
export declare const enforceArchiveSizeLimit: (archiveBytes: number, maxBytes?: number) => Result.Result<void, IngestLimitError>;
|
|
23
|
+
export declare const enforceArchiveContentType: (contentType: string | undefined) => Result.Result<void, IngestUnsupportedContentTypeError>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=ingest-limits.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as Data from "effect/Data";
|
|
2
|
+
import * as Result from "effect/Result";
|
|
3
|
+
export const REGISTRY_PUBLISH_MAX_REQUEST_BYTES = 35 * 1024 * 1024;
|
|
4
|
+
export const REGISTRY_PUBLISH_MAX_ARCHIVE_BYTES = 25 * 1024 * 1024;
|
|
5
|
+
export class IngestLimitError extends Data.TaggedError("IngestLimitError") {
|
|
6
|
+
}
|
|
7
|
+
export class IngestUnsupportedContentTypeError extends Data.TaggedError("IngestUnsupportedContentTypeError") {
|
|
8
|
+
}
|
|
9
|
+
export const enforceRequestSizeLimit = (contentLength, maxBytes = REGISTRY_PUBLISH_MAX_REQUEST_BYTES) => {
|
|
10
|
+
if (contentLength !== undefined && contentLength > maxBytes) {
|
|
11
|
+
return Result.fail(new IngestLimitError({
|
|
12
|
+
code: "ingest_request_too_large",
|
|
13
|
+
detail: `Request body exceeds maximum size of ${maxBytes} bytes.`,
|
|
14
|
+
limit: maxBytes,
|
|
15
|
+
actual: contentLength,
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
return Result.void;
|
|
19
|
+
};
|
|
20
|
+
export const enforceArchiveSizeLimit = (archiveBytes, maxBytes = REGISTRY_PUBLISH_MAX_ARCHIVE_BYTES) => {
|
|
21
|
+
if (archiveBytes > maxBytes) {
|
|
22
|
+
return Result.fail(new IngestLimitError({
|
|
23
|
+
code: "ingest_archive_too_large",
|
|
24
|
+
detail: `Archive exceeds maximum size of ${maxBytes} bytes.`,
|
|
25
|
+
limit: maxBytes,
|
|
26
|
+
actual: archiveBytes,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
return Result.void;
|
|
30
|
+
};
|
|
31
|
+
const V1_ARCHIVE_CONTENT_TYPES = new Set(["application/zip"]);
|
|
32
|
+
export const enforceArchiveContentType = (contentType) => {
|
|
33
|
+
const normalized = contentType?.split(";")[0]?.trim().toLowerCase();
|
|
34
|
+
if (!normalized || !V1_ARCHIVE_CONTENT_TYPES.has(normalized)) {
|
|
35
|
+
return Result.fail(new IngestUnsupportedContentTypeError({
|
|
36
|
+
detail: `Unsupported archive content type: ${contentType ?? "(none)"}. Supported: application/zip.`,
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
return Result.void;
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=ingest-limits.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import type { ExtensionName, ExtensionType } from "@agentxm/extension-model/unstable/extensions";
|
|
3
|
+
import type { Handle } from "@agentxm/extension-model/unstable/extensions/handle";
|
|
4
|
+
import { ArchiveGuardrailError, type ArchiveGuardrailLimits, type ZipEntry } from "./archive-guardrails.js";
|
|
5
|
+
import { type IngestLimitError, type IngestUnsupportedContentTypeError } from "./ingest-limits.js";
|
|
6
|
+
import { type ManifestError, type ResolvedManifest } from "./manifest-policy.js";
|
|
7
|
+
import type { Version } from "@agentxm/extension-model/unstable/version-constraints";
|
|
8
|
+
import { FilteredPackageError } from "./filtered-package-validation.js";
|
|
9
|
+
export interface DeclaredPublishIdentity {
|
|
10
|
+
readonly owner: Handle;
|
|
11
|
+
readonly type: ExtensionType;
|
|
12
|
+
readonly name: ExtensionName;
|
|
13
|
+
readonly version: Version;
|
|
14
|
+
}
|
|
15
|
+
export interface PublishArchiveInput {
|
|
16
|
+
readonly archiveBytes: Uint8Array;
|
|
17
|
+
readonly archiveContentType?: string;
|
|
18
|
+
readonly clientIntegrity?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface NormalizePublishInputArgs {
|
|
21
|
+
readonly declaredIdentity: DeclaredPublishIdentity;
|
|
22
|
+
readonly archive: PublishArchiveInput;
|
|
23
|
+
readonly digestHeader?: string;
|
|
24
|
+
readonly readEntry?: (archiveBytes: Uint8Array, entry: ZipEntry) => Effect.Effect<Uint8Array, ArchiveGuardrailError>;
|
|
25
|
+
readonly guardrailLimits?: ArchiveGuardrailLimits;
|
|
26
|
+
}
|
|
27
|
+
export interface PublishInput {
|
|
28
|
+
readonly owner: Handle;
|
|
29
|
+
readonly type: ExtensionType;
|
|
30
|
+
readonly name: ExtensionName;
|
|
31
|
+
readonly version: Version;
|
|
32
|
+
readonly archiveBytes: Uint8Array;
|
|
33
|
+
readonly archiveContentType: string;
|
|
34
|
+
readonly manifest: ResolvedManifest;
|
|
35
|
+
readonly clientIntegrity?: string;
|
|
36
|
+
readonly digestHeader?: string;
|
|
37
|
+
}
|
|
38
|
+
export declare const defaultReadEntry: (archiveBytes: Uint8Array, entry: ZipEntry) => Effect.Effect<Uint8Array, ArchiveGuardrailError>;
|
|
39
|
+
export declare const normalizePublishInput: (args: NormalizePublishInputArgs) => Effect.Effect<PublishInput, IngestLimitError | IngestUnsupportedContentTypeError | ArchiveGuardrailError | ManifestError | FilteredPackageError>;
|
|
40
|
+
//# sourceMappingURL=input-normalization.d.ts.map
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import { inflateRawSync } from "node:zlib";
|
|
3
|
+
import { ArchiveGuardrailError, ZIP_LOCAL_SIGNATURE, validateArchive, } from "./archive-guardrails.js";
|
|
4
|
+
import { enforceArchiveContentType, enforceArchiveSizeLimit, } from "./ingest-limits.js";
|
|
5
|
+
import { resolveManifest, validateDeclaredManifestAlignment, } from "./manifest-policy.js";
|
|
6
|
+
import { FilteredPackageError, validateFilteredPackage } from "./filtered-package-validation.js";
|
|
7
|
+
const LOCAL_FILE_HEADER_SIZE = 30;
|
|
8
|
+
export const defaultReadEntry = (archiveBytes, entry) => Effect.gen(function* () {
|
|
9
|
+
const { localHeaderOffset, compressedSize, compressionMethod, fileName } = entry;
|
|
10
|
+
if (localHeaderOffset + LOCAL_FILE_HEADER_SIZE > archiveBytes.length) {
|
|
11
|
+
return yield* new ArchiveGuardrailError({
|
|
12
|
+
code: "malformed_archive",
|
|
13
|
+
message: `Local file header for entry "${fileName}" exceeds archive bounds.`,
|
|
14
|
+
entry: fileName,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
const view = new DataView(archiveBytes.buffer, archiveBytes.byteOffset, archiveBytes.byteLength);
|
|
18
|
+
const signature = view.getUint32(localHeaderOffset, true);
|
|
19
|
+
if (signature !== ZIP_LOCAL_SIGNATURE) {
|
|
20
|
+
return yield* new ArchiveGuardrailError({
|
|
21
|
+
code: "malformed_archive",
|
|
22
|
+
message: `Invalid local file header signature for entry "${fileName}".`,
|
|
23
|
+
entry: fileName,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
const fileNameLength = view.getUint16(localHeaderOffset + 26, true);
|
|
27
|
+
const extraFieldLength = view.getUint16(localHeaderOffset + 28, true);
|
|
28
|
+
const dataStart = localHeaderOffset + LOCAL_FILE_HEADER_SIZE + fileNameLength + extraFieldLength;
|
|
29
|
+
if (dataStart + compressedSize > archiveBytes.length) {
|
|
30
|
+
return yield* new ArchiveGuardrailError({
|
|
31
|
+
code: "malformed_archive",
|
|
32
|
+
message: `Compressed data for entry "${fileName}" exceeds archive bounds.`,
|
|
33
|
+
entry: fileName,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const compressedData = archiveBytes.slice(dataStart, dataStart + compressedSize);
|
|
37
|
+
if (compressionMethod === 0) {
|
|
38
|
+
return compressedData;
|
|
39
|
+
}
|
|
40
|
+
if (compressionMethod === 8) {
|
|
41
|
+
// Cap actual decompression at the declared (guardrail-validated) size so a
|
|
42
|
+
// small deflate stream cannot expand into a memory bomb, and route any
|
|
43
|
+
// inflate throw into the typed error channel instead of an uncaught defect.
|
|
44
|
+
const result = yield* Effect.try({
|
|
45
|
+
try: () => inflateRawSync(compressedData, { maxOutputLength: entry.uncompressedSize }),
|
|
46
|
+
catch: (error) => {
|
|
47
|
+
const errorCode = typeof error === "object" &&
|
|
48
|
+
error !== null &&
|
|
49
|
+
"code" in error &&
|
|
50
|
+
typeof error.code === "string"
|
|
51
|
+
? error.code
|
|
52
|
+
: "";
|
|
53
|
+
return errorCode === "ERR_BUFFER_TOO_LARGE"
|
|
54
|
+
? new ArchiveGuardrailError({
|
|
55
|
+
code: "decompression_limit_exceeded",
|
|
56
|
+
message: `Entry "${fileName}" decompresses beyond its declared size of ${entry.uncompressedSize} bytes.`,
|
|
57
|
+
entry: fileName,
|
|
58
|
+
})
|
|
59
|
+
: new ArchiveGuardrailError({
|
|
60
|
+
code: "malformed_archive",
|
|
61
|
+
message: `Failed to decompress entry "${fileName}".`,
|
|
62
|
+
entry: fileName,
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
return new Uint8Array(result.buffer, result.byteOffset, result.byteLength);
|
|
67
|
+
}
|
|
68
|
+
return yield* new ArchiveGuardrailError({
|
|
69
|
+
code: "unsupported_compression",
|
|
70
|
+
message: `Unsupported compression method ${compressionMethod} for entry "${fileName}".`,
|
|
71
|
+
entry: fileName,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
export const normalizePublishInput = (args) => Effect.gen(function* () {
|
|
75
|
+
const { declaredIdentity, archive, digestHeader, guardrailLimits } = args;
|
|
76
|
+
const entryReader = args.readEntry ?? defaultReadEntry;
|
|
77
|
+
yield* Effect.fromResult(enforceArchiveContentType(archive.archiveContentType));
|
|
78
|
+
yield* Effect.fromResult(enforceArchiveSizeLimit(archive.archiveBytes.length));
|
|
79
|
+
const entries = yield* validateArchive(archive.archiveBytes, guardrailLimits);
|
|
80
|
+
const manifest = yield* resolveManifest({
|
|
81
|
+
type: declaredIdentity.type,
|
|
82
|
+
entries,
|
|
83
|
+
readEntry: (fileName) => {
|
|
84
|
+
const entry = entries.find((candidate) => candidate.fileName === fileName);
|
|
85
|
+
if (entry === undefined) {
|
|
86
|
+
return Effect.fail(new ArchiveGuardrailError({
|
|
87
|
+
code: "malformed_archive",
|
|
88
|
+
message: `Entry "${fileName}" not found in archive.`,
|
|
89
|
+
entry: fileName,
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
return entryReader(archive.archiveBytes, entry);
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
yield* Effect.fromResult(validateDeclaredManifestAlignment(declaredIdentity, manifest.identity));
|
|
96
|
+
yield* validateFilteredPackage({
|
|
97
|
+
type: declaredIdentity.type,
|
|
98
|
+
entries,
|
|
99
|
+
manifest,
|
|
100
|
+
readEntry: (fileName) => {
|
|
101
|
+
const entry = entries.find((candidate) => candidate.fileName === fileName);
|
|
102
|
+
return entry === undefined
|
|
103
|
+
? Effect.fail(new FilteredPackageError({
|
|
104
|
+
code: "required_file_missing",
|
|
105
|
+
detail: `Filtered package file "${fileName}" is missing.`,
|
|
106
|
+
path: fileName,
|
|
107
|
+
}))
|
|
108
|
+
: entryReader(archive.archiveBytes, entry);
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
return {
|
|
112
|
+
owner: declaredIdentity.owner,
|
|
113
|
+
type: declaredIdentity.type,
|
|
114
|
+
name: declaredIdentity.name,
|
|
115
|
+
version: declaredIdentity.version,
|
|
116
|
+
archiveBytes: archive.archiveBytes,
|
|
117
|
+
archiveContentType: archive.archiveContentType ?? "application/zip",
|
|
118
|
+
manifest,
|
|
119
|
+
...(archive.clientIntegrity === undefined
|
|
120
|
+
? {}
|
|
121
|
+
: { clientIntegrity: archive.clientIntegrity }),
|
|
122
|
+
...(digestHeader === undefined ? {} : { digestHeader }),
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
//# sourceMappingURL=input-normalization.js.map
|