From a593962b3dbb86ad32209d877126bb39c08865de Mon Sep 17 00:00:00 2001 From: Danijel Martinek Date: Tue, 12 May 2026 22:37:43 +0200 Subject: [PATCH] feat(core-shared/conformance): runtime brand markers + isX predicates --- .../src/conformance/brand-runtime.test.ts | 71 +++++++++++++++++++ .../src/conformance/brand-runtime.ts | 51 +++++++++++++ packages/core-shared/src/conformance/index.ts | 6 ++ 3 files changed, 128 insertions(+) create mode 100644 packages/core-shared/src/conformance/brand-runtime.test.ts create mode 100644 packages/core-shared/src/conformance/brand-runtime.ts diff --git a/packages/core-shared/src/conformance/brand-runtime.test.ts b/packages/core-shared/src/conformance/brand-runtime.test.ts new file mode 100644 index 0000000..f106b8f --- /dev/null +++ b/packages/core-shared/src/conformance/brand-runtime.test.ts @@ -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); + }); +}); diff --git a/packages/core-shared/src/conformance/brand-runtime.ts b/packages/core-shared/src/conformance/brand-runtime.ts new file mode 100644 index 0000000..73e404e --- /dev/null +++ b/packages/core-shared/src/conformance/brand-runtime.ts @@ -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(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)[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"); +} diff --git a/packages/core-shared/src/conformance/index.ts b/packages/core-shared/src/conformance/index.ts index 773dc64..a40ec33 100644 --- a/packages/core-shared/src/conformance/index.ts +++ b/packages/core-shared/src/conformance/index.ts @@ -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";