fix(evidence): enforce the combined record limit
This commit is contained in:
commit
c7918024bc
|
|
@ -62,7 +62,12 @@ export class EvidenceLedger {
|
||||||
? ok("duplicate")
|
? ok("duplicate")
|
||||||
: err(new EvidenceIntegrityError("Conflicting evidence record"));
|
: err(new EvidenceIntegrityError("Conflicting evidence record"));
|
||||||
}
|
}
|
||||||
if (this.#records.size >= this.limits.maxRecords)
|
if (
|
||||||
|
this.#exceedsRecordLimit(
|
||||||
|
this.#records.size + 1,
|
||||||
|
this.#unknownRevisions.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
return err(new EvidenceLimitError("records", this.limits.maxRecords));
|
return err(new EvidenceLimitError("records", this.limits.maxRecords));
|
||||||
const bytes = serializedBytes(evidence);
|
const bytes = serializedBytes(evidence);
|
||||||
if (this.#bytes + bytes > this.limits.maxBytes)
|
if (this.#bytes + bytes > this.limits.maxBytes)
|
||||||
|
|
@ -344,7 +349,7 @@ export class EvidenceLedger {
|
||||||
number,
|
number,
|
||||||
EvidenceIntegrityError | EvidenceLimitError | UnknownRegistryError
|
EvidenceIntegrityError | EvidenceLimitError | UnknownRegistryError
|
||||||
> {
|
> {
|
||||||
if (records.size + unknowns.size > this.limits.maxRecords)
|
if (this.#exceedsRecordLimit(records.size, unknowns.size))
|
||||||
return err(new EvidenceLimitError("records", this.limits.maxRecords));
|
return err(new EvidenceLimitError("records", this.limits.maxRecords));
|
||||||
const bytes =
|
const bytes =
|
||||||
[...records.values()].reduce(
|
[...records.values()].reduce(
|
||||||
|
|
@ -367,6 +372,10 @@ export class EvidenceLedger {
|
||||||
return ok(bytes);
|
return ok(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#exceedsRecordLimit(recordCount: number, unknownCount: number): boolean {
|
||||||
|
return recordCount + unknownCount > this.limits.maxRecords;
|
||||||
|
}
|
||||||
|
|
||||||
#commit(
|
#commit(
|
||||||
records: ReadonlyMap<string, Evidence>,
|
records: ReadonlyMap<string, Evidence>,
|
||||||
unknowns: ReadonlyMap<string, ResidualUnknown>,
|
unknowns: ReadonlyMap<string, ResidualUnknown>,
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,47 @@ describe("analysis evidence", () => {
|
||||||
expect(byteBound.export().records).toEqual([]);
|
expect(byteBound.export().records).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("counts unknown revisions when enforcing direct record limits", () => {
|
||||||
|
const ledger = new EvidenceLedger({
|
||||||
|
maxRecords: 2,
|
||||||
|
maxBytes: 1_000_000,
|
||||||
|
});
|
||||||
|
const mutation = createEvidence(undefined, PROVIDER, {
|
||||||
|
predicateType: "rea.residual-unknown-mutation/v1",
|
||||||
|
operation: "record_unknown",
|
||||||
|
parameters: {},
|
||||||
|
result: { action: "record" },
|
||||||
|
});
|
||||||
|
const unknown = recordUnknownInputSchema.parse({
|
||||||
|
approved: true,
|
||||||
|
question: "What remains unresolved?",
|
||||||
|
severity: "high",
|
||||||
|
domain: "record-limit-test",
|
||||||
|
supporting_evidence_ids: [],
|
||||||
|
contradicting_evidence_ids: [],
|
||||||
|
required_authority: "shipped-artifact",
|
||||||
|
required_confidence: "observed",
|
||||||
|
required_environment: null,
|
||||||
|
recommended_probes: [],
|
||||||
|
relationships: [],
|
||||||
|
});
|
||||||
|
expect(ledger.recordUnknown(unknown, mutation).ok).toBe(true);
|
||||||
|
|
||||||
|
const direct = createEvidence(TARGET, PROVIDER, {
|
||||||
|
operation: "health",
|
||||||
|
parameters: {},
|
||||||
|
result: true,
|
||||||
|
});
|
||||||
|
expect(ledger.record(direct)).toMatchObject({
|
||||||
|
ok: false,
|
||||||
|
error: { _tag: "EvidenceLimitError", limit: "records", maximum: 2 },
|
||||||
|
});
|
||||||
|
expect(ledger.export()).toMatchObject({
|
||||||
|
records: [mutation],
|
||||||
|
unknowns: [expect.objectContaining({ domain: "record-limit-test" })],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("derives byte-stable manifests independent of record insertion order", () => {
|
it("derives byte-stable manifests independent of record insertion order", () => {
|
||||||
const artifactEvidence = createEvidence(TARGET, PROVIDER, {
|
const artifactEvidence = createEvidence(TARGET, PROVIDER, {
|
||||||
operation: "health",
|
operation: "health",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue