mirror of
https://github.com/morluto/rea.git
synced 2026-11-05 14:26:07 +00:00
refactor(javascript): group domain semantics and contracts (#907)
This commit is contained in:
1 parent
d5f28fb29c
commit
f6a58f1062
253 files changed
+432
-410
No files matched your search
@@ -0,0 +1,480 @@
|
||||
import { z } from "zod";
|
||||
import { digestSchema } from "../digests.js";
|
||||
import { prefixedDigestSchema } from "../digests.js";
|
||||
|
||||
const boundedTextSchema = z.string().min(1);
|
||||
const boundedKeySchema = z.string().min(1);
|
||||
const unsafePathSegments = new Set(["", ".", ".."]);
|
||||
const isSafeRelativePath = (path: string): boolean => {
|
||||
if (path.startsWith("/") || path.includes("\\")) return false;
|
||||
return path.split("/").every((part) => !unsafePathSegments.has(part));
|
||||
};
|
||||
const relativePathSchema = z
|
||||
.string()
|
||||
.min(1)
|
||||
.refine(
|
||||
isSafeRelativePath,
|
||||
"Expected a normalized relative POSIX path without traversal",
|
||||
);
|
||||
|
||||
/** Authority that produced one node observation or relationship. */
|
||||
const applicationEvidenceAuthoritySchema = z.enum([
|
||||
"artifact-bytes",
|
||||
"ast-static-analysis",
|
||||
"static-relationship-inference",
|
||||
"passive-cdp-runtime",
|
||||
"cross-layer-reconciliation",
|
||||
"cross-version-comparison",
|
||||
"controlled-replay",
|
||||
"native-analysis-provider",
|
||||
"managed-static-analysis",
|
||||
"historical-reference",
|
||||
"user-assertion",
|
||||
"unknown",
|
||||
]);
|
||||
|
||||
/** Epistemic state kept separate from the evidence source. */
|
||||
const applicationFactStateSchema = z.enum([
|
||||
"observed",
|
||||
"inferred",
|
||||
"unknown",
|
||||
"unavailable",
|
||||
]);
|
||||
|
||||
/** Confidence assigned without promoting inference into observation. */
|
||||
const applicationConfidenceSchema = z.enum([
|
||||
"exact",
|
||||
"high",
|
||||
"medium",
|
||||
"low",
|
||||
"unknown",
|
||||
]);
|
||||
|
||||
/** Why an artifact or source location was not available to an extractor. */
|
||||
const applicationUnavailableReasonSchema = z.enum([
|
||||
"not-applicable",
|
||||
"not-observed",
|
||||
"truncated",
|
||||
"provider-unavailable",
|
||||
"unresolved",
|
||||
"unknown",
|
||||
]);
|
||||
|
||||
const unavailableFactSchema = z.strictObject({
|
||||
available: z.literal(false),
|
||||
reason: applicationUnavailableReasonSchema,
|
||||
detail: boundedTextSchema,
|
||||
});
|
||||
|
||||
const availableArtifactSchema = z
|
||||
.strictObject({
|
||||
available: z.literal(true),
|
||||
artifact_id: prefixedDigestSchema("art"),
|
||||
sha256: digestSchema,
|
||||
})
|
||||
.superRefine((artifact, context) => {
|
||||
if (artifact.artifact_id !== `art_${artifact.sha256}`)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["artifact_id"],
|
||||
message: "Artifact identifier must commit the same SHA-256 digest",
|
||||
});
|
||||
});
|
||||
|
||||
/** Explicit content-addressed artifact availability for one graph fact. */
|
||||
const applicationArtifactReferenceSchema = z.discriminatedUnion("available", [
|
||||
availableArtifactSchema,
|
||||
unavailableFactSchema,
|
||||
]);
|
||||
|
||||
const sourceRangeSchema = z
|
||||
.strictObject({
|
||||
kind: z.literal("source-range"),
|
||||
source: boundedTextSchema,
|
||||
start: z.strictObject({
|
||||
line: z.number().int().min(1),
|
||||
column: z.number().int().min(0),
|
||||
}),
|
||||
end: z.strictObject({
|
||||
line: z.number().int().min(1),
|
||||
column: z.number().int().min(0),
|
||||
}),
|
||||
})
|
||||
.superRefine((location, context) => {
|
||||
if (
|
||||
location.end.line < location.start.line ||
|
||||
(location.end.line === location.start.line &&
|
||||
location.end.column < location.start.column)
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["end"],
|
||||
message: "Source range end must not precede its start",
|
||||
});
|
||||
});
|
||||
|
||||
const fileOffsetRangeSchema = z
|
||||
.strictObject({
|
||||
kind: z.literal("file-offset-range"),
|
||||
start: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
||||
end: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
||||
})
|
||||
.superRefine((location, context) => {
|
||||
if (location.end < location.start)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["end"],
|
||||
message: "File offset range end must not precede its start",
|
||||
});
|
||||
});
|
||||
|
||||
/** A deterministic artifact, source, runtime, package, or native location. */
|
||||
const applicationLocationSchema = z.discriminatedUnion("kind", [
|
||||
z.strictObject({
|
||||
kind: z.literal("artifact-path"),
|
||||
path: relativePathSchema,
|
||||
}),
|
||||
sourceRangeSchema,
|
||||
fileOffsetRangeSchema,
|
||||
z.strictObject({
|
||||
kind: z.literal("url"),
|
||||
url: z.string().min(1),
|
||||
}),
|
||||
z.strictObject({
|
||||
kind: z.literal("runtime"),
|
||||
capture_sha256: digestSchema,
|
||||
target_key: boundedKeySchema,
|
||||
frame_key: boundedKeySchema.nullable(),
|
||||
script_key: boundedKeySchema.nullable(),
|
||||
}),
|
||||
z.strictObject({
|
||||
kind: z.literal("native-address"),
|
||||
address: boundedKeySchema,
|
||||
symbol: boundedTextSchema.nullable(),
|
||||
}),
|
||||
z.strictObject({
|
||||
kind: z.literal("package-export"),
|
||||
package_name: boundedKeySchema,
|
||||
export_path: boundedTextSchema,
|
||||
}),
|
||||
]);
|
||||
|
||||
/** Explicit source-location availability for one graph fact. */
|
||||
const applicationLocationReferenceSchema = z.discriminatedUnion("available", [
|
||||
z.strictObject({
|
||||
available: z.literal(true),
|
||||
value: applicationLocationSchema,
|
||||
}),
|
||||
unavailableFactSchema,
|
||||
]);
|
||||
|
||||
/** Versioned extractor coordinates attached to every graph fact. */
|
||||
const applicationExtractorSchema = z.strictObject({
|
||||
name: z.string().min(1),
|
||||
version: z.string().min(1),
|
||||
operation: z.string().min(1),
|
||||
executable_sha256: digestSchema.nullable(),
|
||||
});
|
||||
|
||||
const applicationLimitSchema = z.strictObject({
|
||||
name: z.string().min(1),
|
||||
value: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
||||
unit: z.enum([
|
||||
"items",
|
||||
"bytes",
|
||||
"milliseconds",
|
||||
"depth",
|
||||
"characters",
|
||||
"instructions",
|
||||
"other",
|
||||
]),
|
||||
});
|
||||
|
||||
/** Bounded collection coverage without treating omission as absence. */
|
||||
const coverageLimitsSchema = z.array(applicationLimitSchema);
|
||||
const omittedCountSchema = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
|
||||
|
||||
export const applicationCoverageSchema = z.union([
|
||||
z.strictObject({
|
||||
status: z.literal("complete"),
|
||||
truncated: z.literal(false),
|
||||
omitted_count: z.literal(0),
|
||||
limits: coverageLimitsSchema,
|
||||
}),
|
||||
z.strictObject({
|
||||
status: z.literal("partial"),
|
||||
truncated: z.literal(false),
|
||||
omitted_count: omittedCountSchema.nullable(),
|
||||
limits: coverageLimitsSchema,
|
||||
}),
|
||||
z.strictObject({
|
||||
status: z.literal("partial"),
|
||||
truncated: z.literal(true),
|
||||
omitted_count: z.union([omittedCountSchema.positive(), z.null()]),
|
||||
limits: z.array(applicationLimitSchema).min(1),
|
||||
}),
|
||||
z.strictObject({
|
||||
status: z.enum(["unknown", "unavailable"]),
|
||||
truncated: z.literal(false),
|
||||
omitted_count: z.null(),
|
||||
limits: coverageLimitsSchema,
|
||||
}),
|
||||
]);
|
||||
export type ApplicationCoverage = z.infer<typeof applicationCoverageSchema>;
|
||||
|
||||
/** Construct complete bounded coverage under the stated configured limits. */
|
||||
export const completeApplicationCoverage = (
|
||||
limits: ApplicationCoverage["limits"] = [],
|
||||
): ApplicationCoverage =>
|
||||
applicationCoverageSchema.parse({
|
||||
status: "complete",
|
||||
truncated: false,
|
||||
omitted_count: 0,
|
||||
limits,
|
||||
});
|
||||
|
||||
/** Construct partial non-truncated coverage without inventing omissions. */
|
||||
export const partialApplicationCoverage = (
|
||||
limits: ApplicationCoverage["limits"],
|
||||
omittedCount: number | null,
|
||||
): ApplicationCoverage =>
|
||||
applicationCoverageSchema.parse({
|
||||
status: "partial",
|
||||
truncated: false,
|
||||
omitted_count: omittedCount,
|
||||
limits,
|
||||
});
|
||||
|
||||
/** Construct limit-truncated coverage with a named bound. */
|
||||
export const truncatedApplicationCoverage = (
|
||||
limits: ApplicationCoverage["limits"],
|
||||
omittedCount: number | null,
|
||||
): ApplicationCoverage =>
|
||||
applicationCoverageSchema.parse({
|
||||
status: "partial",
|
||||
truncated: true,
|
||||
omitted_count: omittedCount,
|
||||
limits,
|
||||
});
|
||||
|
||||
const applicationGraphEvidenceBaseSchema = z.strictObject({
|
||||
authority: applicationEvidenceAuthoritySchema,
|
||||
state: applicationFactStateSchema,
|
||||
confidence: applicationConfidenceSchema,
|
||||
artifact: applicationArtifactReferenceSchema,
|
||||
location: applicationLocationReferenceSchema,
|
||||
extractor: applicationExtractorSchema,
|
||||
coverage: applicationCoverageSchema,
|
||||
limitations: z.array(boundedTextSchema),
|
||||
evidence_ids: z.array(prefixedDigestSchema("ev")),
|
||||
});
|
||||
|
||||
type EvidenceValue = z.infer<typeof applicationGraphEvidenceBaseSchema>;
|
||||
|
||||
const checkAuthorityState = (
|
||||
evidence: EvidenceValue,
|
||||
context: z.RefinementCtx,
|
||||
): void => {
|
||||
if (
|
||||
evidence.authority === "static-relationship-inference" &&
|
||||
evidence.state !== "inferred"
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["state"],
|
||||
message: "Static relationship authority must remain inferred",
|
||||
});
|
||||
if (
|
||||
evidence.authority === "cross-layer-reconciliation" &&
|
||||
evidence.state !== "inferred"
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["state"],
|
||||
message: "Cross-layer reconciliation authority must remain inferred",
|
||||
});
|
||||
if (
|
||||
evidence.authority === "cross-version-comparison" &&
|
||||
evidence.state !== "inferred"
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["state"],
|
||||
message: "Cross-version comparison authority must remain inferred",
|
||||
});
|
||||
if (
|
||||
evidence.authority === "unknown" &&
|
||||
!["unknown", "unavailable"].includes(evidence.state)
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["state"],
|
||||
message: "Unknown authority cannot claim an observed fact",
|
||||
});
|
||||
};
|
||||
|
||||
const checkStateConfidence = (
|
||||
evidence: EvidenceValue,
|
||||
context: z.RefinementCtx,
|
||||
): void => {
|
||||
if (
|
||||
["unknown", "unavailable"].includes(evidence.state) &&
|
||||
(evidence.confidence !== "unknown" || evidence.limitations.length === 0)
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
message:
|
||||
"Unknown and unavailable facts require unknown confidence and an explicit limitation",
|
||||
});
|
||||
if (evidence.state === "observed" && evidence.confidence === "unknown")
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["confidence"],
|
||||
message: "Observed facts require a bounded non-unknown confidence",
|
||||
});
|
||||
if (
|
||||
evidence.state === "inferred" &&
|
||||
!["high", "medium", "low"].includes(evidence.confidence)
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["confidence"],
|
||||
message: "Inferred facts require high, medium, or low confidence",
|
||||
});
|
||||
if (evidence.confidence === "exact" && evidence.state !== "observed")
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["confidence"],
|
||||
message: "Exact confidence is reserved for observed facts",
|
||||
});
|
||||
};
|
||||
|
||||
const checkTraceability = (
|
||||
evidence: EvidenceValue,
|
||||
context: z.RefinementCtx,
|
||||
): void => {
|
||||
if (evidence.state === "observed" && !evidence.location.available)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["location"],
|
||||
message: "Observed facts require an actionable location",
|
||||
});
|
||||
if (evidence.state === "inferred" && evidence.limitations.length === 0)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["limitations"],
|
||||
message: "Inferred facts require an explicit limitation",
|
||||
});
|
||||
if (
|
||||
evidence.coverage.status !== "complete" &&
|
||||
evidence.limitations.length === 0
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["limitations"],
|
||||
message: "Non-complete coverage requires an explicit limitation",
|
||||
});
|
||||
};
|
||||
|
||||
const checkArtifactBacking = (
|
||||
evidence: EvidenceValue,
|
||||
context: z.RefinementCtx,
|
||||
): void => {
|
||||
const artifactBacked = [
|
||||
"artifact-bytes",
|
||||
"ast-static-analysis",
|
||||
"controlled-replay",
|
||||
"native-analysis-provider",
|
||||
"managed-static-analysis",
|
||||
].includes(evidence.authority);
|
||||
if (
|
||||
artifactBacked &&
|
||||
evidence.state !== "unavailable" &&
|
||||
!evidence.artifact.available
|
||||
)
|
||||
context.addIssue({
|
||||
code: "custom",
|
||||
path: ["artifact"],
|
||||
message: "Artifact-backed facts require a content digest",
|
||||
});
|
||||
};
|
||||
|
||||
/** Provenance, authority, uncertainty, and bounds for one graph fact. */
|
||||
export const applicationGraphEvidenceSchema =
|
||||
applicationGraphEvidenceBaseSchema.superRefine((evidence, context) => {
|
||||
checkAuthorityState(evidence, context);
|
||||
checkStateConfidence(evidence, context);
|
||||
checkTraceability(evidence, context);
|
||||
checkArtifactBacking(evidence, context);
|
||||
});
|
||||
|
||||
/** Stable node identifier strategies and their explicit scope. */
|
||||
export const applicationNodeIdentitySchema = z.discriminatedUnion("strategy", [
|
||||
z.strictObject({
|
||||
strategy: z.literal("content-digest"),
|
||||
stability: z.literal("global-exact"),
|
||||
sha256: digestSchema,
|
||||
}),
|
||||
z.strictObject({
|
||||
strategy: z.literal("source-map-original"),
|
||||
stability: z.literal("source-map-exact"),
|
||||
source_map_sha256: digestSchema,
|
||||
// The exact `sources` entry; `""` is a legal relative reference.
|
||||
original_source: z.string(),
|
||||
source_sha256: digestSchema.nullable(),
|
||||
}),
|
||||
z.strictObject({
|
||||
strategy: z.literal("canonical-path"),
|
||||
stability: z.literal("artifact-version"),
|
||||
artifact_sha256: digestSchema,
|
||||
path: relativePathSchema,
|
||||
}),
|
||||
z.strictObject({
|
||||
strategy: z.literal("structural-fingerprint"),
|
||||
stability: z.literal("cross-version-inference"),
|
||||
algorithm: z.string().min(1),
|
||||
fingerprint_sha256: digestSchema,
|
||||
basis: z
|
||||
.array(
|
||||
z.enum([
|
||||
"syntax-tree",
|
||||
"control-flow",
|
||||
"imports",
|
||||
"exports",
|
||||
"literals",
|
||||
"api-usage",
|
||||
]),
|
||||
)
|
||||
.min(1),
|
||||
}),
|
||||
z.strictObject({
|
||||
strategy: z.literal("artifact-local-key"),
|
||||
stability: z.literal("artifact-version"),
|
||||
artifact_sha256: digestSchema,
|
||||
namespace: boundedKeySchema,
|
||||
// The exact artifact-local value, such as `""` from `fetch("")`.
|
||||
key: z.string(),
|
||||
}),
|
||||
z.strictObject({
|
||||
strategy: z.literal("runtime-instance"),
|
||||
stability: z.literal("capture-only"),
|
||||
capture_sha256: digestSchema,
|
||||
runtime_key: boundedTextSchema,
|
||||
}),
|
||||
z.strictObject({
|
||||
strategy: z.literal("observation-fingerprint"),
|
||||
stability: z.literal("observation-only"),
|
||||
observation_sha256: digestSchema,
|
||||
scope: boundedTextSchema,
|
||||
}),
|
||||
]);
|
||||
|
||||
/** Evidence coordinates attached to one graph observation or edge. */
|
||||
export type ApplicationGraphEvidence = z.infer<
|
||||
typeof applicationGraphEvidenceSchema
|
||||
>;
|
||||
|
||||
/** Explicit stable identity strategy for one application entity. */
|
||||
export type ApplicationNodeIdentity = z.infer<
|
||||
typeof applicationNodeIdentitySchema
|
||||
>;
|
||||
Reference in new issue
Block a user