feat(core-shared/conformance): runtime brand markers + isX predicates

This commit is contained in:
2026-05-12 22:37:43 +02:00
parent 198765ff06
commit a593962b3d
3 changed files with 128 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
import { describe, it, expect } from "vitest";
import {
attachBrand,
isInstrumented,
isCaptured,
isAudited,
} from "@/conformance/brand-runtime";
describe("brand-runtime", () => {
it("attachBrand adds a non-enumerable property and returns the same reference", () => {
const fn = () => {};
const result = attachBrand(fn, "__instrumented");
expect(result).toBe(fn);
expect(isInstrumented(fn)).toBe(true);
// Non-enumerable: must not show up in Object.keys
expect(Object.keys(fn)).not.toContain("__instrumented");
});
it("predicates return false for unwrapped functions", () => {
const fn = () => {};
expect(isInstrumented(fn)).toBe(false);
expect(isCaptured(fn)).toBe(false);
expect(isAudited(fn)).toBe(false);
});
it("predicates discriminate between brands", () => {
const instrumented = () => {};
attachBrand(instrumented, "__instrumented");
expect(isInstrumented(instrumented)).toBe(true);
expect(isCaptured(instrumented)).toBe(false);
expect(isAudited(instrumented)).toBe(false);
const captured = () => {};
attachBrand(captured, "__captured");
expect(isInstrumented(captured)).toBe(false);
expect(isCaptured(captured)).toBe(true);
expect(isAudited(captured)).toBe(false);
const audited = () => {};
attachBrand(audited, "__audited");
expect(isAudited(audited)).toBe(true);
});
it("composing brands stacks them on the same function", () => {
const fn = () => {};
attachBrand(fn, "__instrumented");
attachBrand(fn, "__captured");
attachBrand(fn, "__audited");
expect(isInstrumented(fn)).toBe(true);
expect(isCaptured(fn)).toBe(true);
expect(isAudited(fn)).toBe(true);
});
it("attached brands are non-writable and non-configurable", () => {
const fn = () => {};
attachBrand(fn, "__instrumented");
const desc = Object.getOwnPropertyDescriptor(fn, "__instrumented");
expect(desc?.writable).toBe(false);
expect(desc?.configurable).toBe(false);
expect(desc?.enumerable).toBe(false);
expect(desc?.value).toBe(true);
});
it("predicates return false for non-function inputs", () => {
expect(isInstrumented(null)).toBe(false);
expect(isInstrumented(undefined)).toBe(false);
expect(isInstrumented(42)).toBe(false);
expect(isInstrumented("string")).toBe(false);
expect(isInstrumented({})).toBe(false);
});
});

View File

@@ -0,0 +1,51 @@
/**
* Runtime brand attachment + predicates. The companion to the phantom-type
* brands defined in `./brands.ts`: at compile time the brand is a structural
* intersection; at runtime it is a non-enumerable, non-writable,
* non-configurable property with the same name.
*
* Why non-enumerable: a wrapped function should not leak the marker through
* `Object.keys`, `JSON.stringify`, `for…in`, or spread. The marker only
* shows up to explicit lookups via `Reflect.has` or direct property access.
*
* Why non-writable + non-configurable: the marker is meant to be permanent
* once attached. The wrapper is the only caller; the marker is a one-shot
* commitment, not a mutable flag.
*/
type Brand = "__instrumented" | "__captured" | "__audited";
/**
* Attaches the brand as a non-enumerable property on the given function.
* Returns the same reference (no allocation). Idempotent: calling twice with
* the same brand throws because the property is non-configurable — wrappers
* never double-wrap, so this is the correct safety net.
*/
export function attachBrand<F extends object>(fn: F, brand: Brand): F {
Object.defineProperty(fn, brand, {
value: true,
enumerable: false,
writable: false,
configurable: false,
});
return fn;
}
function hasBrand(fn: unknown, brand: Brand): boolean {
if (typeof fn !== "function" && (typeof fn !== "object" || fn === null)) {
return false;
}
return (fn as Record<string, unknown>)[brand] === true;
}
export function isInstrumented(fn: unknown): boolean {
return hasBrand(fn, "__instrumented");
}
export function isCaptured(fn: unknown): boolean {
return hasBrand(fn, "__captured");
}
export function isAudited(fn: unknown): boolean {
return hasBrand(fn, "__audited");
}

View File

@@ -2,3 +2,9 @@ export type { Instrumented, Captured } from "./brands";
export type { FeatureManifest, UseCaseManifest } from "./define-feature";
export { defineFeature } from "./define-feature";
export type { ProductionUseCase } from "./production-use-case";
export {
attachBrand,
isInstrumented,
isCaptured,
isAudited,
} from "./brand-runtime";