🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@mochi.js/profiles

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mochi.js/profiles - npm Package Compare versions

Comparing version
0.1.1
to
0.2.0
+1
-1
data/linux-chrome-stable/expected-divergences.json

@@ -111,3 +111,3 @@ {

"path": "bot.chromeRuntime",
"comment": "Real Chrome exposes window.chrome.runtime; Chromium-for-Testing does not. Restoring chrome.runtime polyfill is task 0140 (stealth conformance) — tracked separately."
"comment": "Real Chrome exposes window.chrome.runtime; Chromium-for-Testing does not. Restoring chrome.runtime polyfill."
},

@@ -114,0 +114,0 @@ {

@@ -19,9 +19,9 @@ {

"model": "generic-x64",
"cpuFamily": "intel-core",
"cores": 32,
"memoryGB": 64
"cpuFamily": "intel-core-i7",
"cores": 8,
"memoryGB": 16
},
"display": {
"width": 1280,
"height": 800,
"width": 1920,
"height": 1080,
"dpr": 1,

@@ -32,6 +32,6 @@ "colorDepth": 24,

"gpu": {
"vendor": "Google Inc.",
"renderer": "Generic Renderer",
"webglUnmaskedVendor": "Google Inc.",
"webglUnmaskedRenderer": "ANGLE (Generic)",
"vendor": "Intel Inc.",
"renderer": "Intel Iris Xe Graphics",
"webglUnmaskedVendor": "Google Inc. (Intel Inc.)",
"webglUnmaskedRenderer": "ANGLE (Intel Inc., Intel Iris Xe Graphics, OpenGL 4.1)",
"webglMaxTextureSize": 16384,

@@ -77,3 +77,3 @@ "webglMaxColorAttachments": 8,

"uaCh": {
"sec-ch-ua": "\"Chromium\";v=\"147\", \"Not.A/Brand\";v=\"8\"",
"sec-ch-ua": "\"Google Chrome\";v=\"147\", \"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"147\"",
"sec-ch-ua-mobile": "?0",

@@ -85,4 +85,3 @@ "sec-ch-ua-platform": "\"Linux\"",

"sec-ch-ua-model": "\"\"",
"sec-ch-ua-full-version": "\"147\"",
"sec-ch-ua-os": "\"linux\""
"sec-ch-ua-full-version": "\"147.0.7727.138\""
},

@@ -89,0 +88,0 @@ "entropyBudget": {

@@ -15,3 +15,3 @@ # PROVENANCE — linux-chrome-stable

| imported at (UTC) | 2026-05-08T20:50:37.035Z |
| importer | `mochi profiles import` (task 0260) |
| importer | `mochi profiles import` |

@@ -28,3 +28,3 @@ ## Multi-snapshot policy

None at import time. The harvester's `navigator` snapshot is captured by real Chrome (not headless), so the `--headless=new` artifacts that needed manual correction in `mac-m4-chrome-stable` (task 0070) are absent here.
None at import time. The harvester's `navigator` snapshot is captured by real Chrome (not headless), so the `--headless=new` artifacts that needed manual correction in `mac-m4-chrome-stable` are absent here.

@@ -111,3 +111,3 @@ {

"path": "bot.chromeRuntime",
"comment": "Real Chrome exposes window.chrome.runtime; Chromium-for-Testing does not. Restoring chrome.runtime polyfill is task 0140 (stealth conformance) — tracked separately."
"comment": "Real Chrome exposes window.chrome.runtime; Chromium-for-Testing does not. Restoring chrome.runtime polyfill."
},

@@ -114,0 +114,0 @@ {

@@ -15,3 +15,3 @@ # PROVENANCE — mac-brave-stable

| imported at (UTC) | 2026-05-08T20:50:38.368Z |
| importer | `mochi profiles import` (task 0260) |
| importer | `mochi profiles import` |

@@ -28,3 +28,3 @@ ## Multi-snapshot policy

None at import time. The harvester's `navigator` snapshot is captured by real Chrome (not headless), so the `--headless=new` artifacts that needed manual correction in `mac-m4-chrome-stable` (task 0070) are absent here.
None at import time. The harvester's `navigator` snapshot is captured by real Chrome (not headless), so the `--headless=new` artifacts that needed manual correction in `mac-m4-chrome-stable` are absent here.

@@ -111,3 +111,3 @@ {

"path": "bot.chromeRuntime",
"comment": "Real Chrome exposes window.chrome.runtime; Chromium-for-Testing does not. Restoring chrome.runtime polyfill is task 0140 (stealth conformance) — tracked separately."
"comment": "Real Chrome exposes window.chrome.runtime; Chromium-for-Testing does not. Restoring chrome.runtime polyfill."
},

@@ -114,0 +114,0 @@ {

@@ -15,3 +15,3 @@ # PROVENANCE — mac-chrome-beta

| imported at (UTC) | 2026-05-08T20:50:35.794Z |
| importer | `mochi profiles import` (task 0260) |
| importer | `mochi profiles import` |

@@ -28,3 +28,3 @@ ## Multi-snapshot policy

None at import time. The harvester's `navigator` snapshot is captured by real Chrome (not headless), so the `--headless=new` artifacts that needed manual correction in `mac-m4-chrome-stable` (task 0070) are absent here.
None at import time. The harvester's `navigator` snapshot is captured by real Chrome (not headless), so the `--headless=new` artifacts that needed manual correction in `mac-m4-chrome-stable` are absent here.

@@ -111,3 +111,3 @@ {

"path": "bot.chromeRuntime",
"comment": "Real Chrome exposes window.chrome.runtime; Chromium-for-Testing does not. Restoring chrome.runtime polyfill is task 0140 (stealth conformance) — tracked separately."
"comment": "Real Chrome exposes window.chrome.runtime; Chromium-for-Testing does not. Restoring chrome.runtime polyfill."
},

@@ -114,0 +114,0 @@ {

@@ -15,3 +15,3 @@ # PROVENANCE — mac-chrome-stable

| imported at (UTC) | 2026-05-08T20:50:33.447Z |
| importer | `mochi profiles import` (task 0260) |
| importer | `mochi profiles import` |

@@ -28,3 +28,3 @@ ## Multi-snapshot policy

None at import time. The harvester's `navigator` snapshot is captured by real Chrome (not headless), so the `--headless=new` artifacts that needed manual correction in `mac-m4-chrome-stable` (task 0070) are absent here.
None at import time. The harvester's `navigator` snapshot is captured by real Chrome (not headless), so the `--headless=new` artifacts that needed manual correction in `mac-m4-chrome-stable` are absent here.

@@ -17,3 +17,3 @@ # PROVENANCE — mac-m4-chrome-stable

- 2026-05-08, task 0051: `uaCh.sec-ch-ua-model` corrected from `"\"Mac\""`
- 2026-05-08, `uaCh.sec-ch-ua-model` corrected from `"\"Mac\""`
to `"\"\""` (empty quoted string). Real Chrome 147 desktop reports

@@ -26,3 +26,3 @@ `model: ""` from `getHighEntropyValues`; the v0.4 capture incorrectly

- 2026-05-08, task 0070: headless-mode-leak corrections in
- 2026-05-08, headless-mode-leak corrections in
`baseline.manifest.json` + `profile.json`. The original capture ran

@@ -29,0 +29,0 @@ against `--headless=new` Chromium-for-Testing, which emits several

@@ -111,3 +111,3 @@ {

"path": "bot.chromeRuntime",
"comment": "Real Chrome exposes window.chrome.runtime; Chromium-for-Testing does not. Restoring chrome.runtime polyfill is task 0140 (stealth conformance) — tracked separately."
"comment": "Real Chrome exposes window.chrome.runtime; Chromium-for-Testing does not. Restoring chrome.runtime polyfill."
},

@@ -114,0 +114,0 @@ {

@@ -15,3 +15,3 @@ # PROVENANCE — windows-chrome-stable

| imported at (UTC) | 2026-05-08T20:50:36.301Z |
| importer | `mochi profiles import` (task 0260) |
| importer | `mochi profiles import` |

@@ -28,3 +28,3 @@ ## Multi-snapshot policy

None at import time. The harvester's `navigator` snapshot is captured by real Chrome (not headless), so the `--headless=new` artifacts that needed manual correction in `mac-m4-chrome-stable` (task 0070) are absent here.
None at import time. The harvester's `navigator` snapshot is captured by real Chrome (not headless), so the `--headless=new` artifacts that needed manual correction in `mac-m4-chrome-stable` are absent here.
{
"name": "@mochi.js/profiles",
"version": "0.1.1",
"version": "0.2.0",
"description": "Profile data fixtures for mochi — captured baselines (profile.json + Probe Manifest + audio bytes + canvas hashes) per device class.",

@@ -42,3 +42,3 @@ "license": "MIT",

"dependencies": {
"@mochi.js/consistency": "^0.1.3"
"@mochi.js/consistency": "^0.1.4"
},

@@ -45,0 +45,0 @@ "publishConfig": {

import { describe, expect, it } from "bun:test";
import { getProfile, KNOWN_PROFILE_IDS, VERSION } from "../index";
import {
getProfile,
hasProfile,
KNOWN_PROFILE_IDS,
ProfileBaselineMissingError,
UnknownProfileIdError,
VERSION,
} from "../index";
describe("@mochi.js/profiles (claim release)", () => {
describe("@mochi.js/profiles", () => {
it("exports VERSION", () => {

@@ -14,5 +21,48 @@ expect(VERSION).toMatch(/^\d+\.\d+\.\d+/);

it("getProfile throws until phase 0.4", () => {
expect(() => getProfile("mac-m2-chrome-stable")).toThrow(/not yet implemented/);
it("getProfile loads a captured baseline (linux-chrome-stable)", async () => {
const p = await getProfile("linux-chrome-stable");
expect(p.id).toBe("linux-chrome-stable");
expect(p.engine).toBe("chromium");
// The captured Linux baseline pins Chrome 147 — guards against the
// regression where launch.ts's placeholder shipped Chrome/131 to users.
expect(p.browser.name).toBe("chrome");
expect(Number.parseInt(p.browser.minVersion, 10)).toBeGreaterThanOrEqual(147);
expect(p.os.name).toBe("linux");
expect(p.userAgent).toMatch(/Chrome\/\d+/);
});
it("getProfile loads every captured baseline declared in PROFILES_WITH_CAPTURED_BASELINE", async () => {
// Sanity: every id reported as having a baseline by hasProfile() must
// also load via getProfile() without throwing.
for (const id of KNOWN_PROFILE_IDS) {
const has = await hasProfile(id);
if (!has) continue;
const p = await getProfile(id);
expect(p.id).toBe(id);
}
});
it("hasProfile returns true for ids with a captured baseline", async () => {
expect(await hasProfile("linux-chrome-stable")).toBe(true);
expect(await hasProfile("mac-m4-chrome-stable")).toBe(true);
});
it("hasProfile returns false for known ids without a captured baseline", async () => {
expect(await hasProfile("mac-m2-chrome-stable")).toBe(false);
});
it("hasProfile returns false for unknown ids", async () => {
expect(await hasProfile("not-a-real-profile-id")).toBe(false);
});
it("getProfile throws ProfileBaselineMissingError for known ids without a baseline", async () => {
await expect(getProfile("mac-m2-chrome-stable")).rejects.toThrow(ProfileBaselineMissingError);
});
it("getProfile throws UnknownProfileIdError for ids outside the catalog", async () => {
// Cast through unknown — callers using `as ProfileId` may slip past TS.
await expect(getProfile("not-a-real-profile-id" as never)).rejects.toThrow(
UnknownProfileIdError,
);
});
});
// AUTO-GENERATED — do not edit. Run `bun run codegen` to regenerate.
// Source schema lives in schemas/. See scripts/codegen.ts and tasks/0003-schemas-and-codegen.md.
// Source schema lives in schemas/. See scripts/codegen.ts.
// Re-export of the canonical ProfileV1 type from @mochi.js/consistency.

@@ -4,0 +4,0 @@ // @mochi.js/profiles is a data-fixture package; the type lives in consistency

@@ -11,6 +11,6 @@ /**

*
* v0.0.1 claim release; first profile (`mac-m2-chrome-stable`) lands in phase 0.4.
*
* @see PLAN.md §5.6 and §12
*/
import { join } from "node:path";
export const VERSION = "0.0.1" as const;

@@ -23,2 +23,4 @@

import type { ProfileV1 } from "./generated/profile";
/** ProfileV1 IDs that ship in the v1 catalog. */

@@ -33,3 +35,3 @@ export const KNOWN_PROFILE_IDS = [

"linux-chrome-stable",
// Imported from harvester corpus per task 0260.
// Imported from harvester corpus per
"mac-chrome-stable",

@@ -44,9 +46,103 @@ "mac-chrome-beta",

/**
* Resolve a profile by id. Lands in phase 0.4 when the first baseline is captured.
* The subset of {@link KNOWN_PROFILE_IDS} for which a captured baseline
* (`data/<id>/profile.json`) actually ships in the npm package. The rest are
* declared in the catalog so the type system tracks them, but {@link getProfile}
* throws {@link ProfileBaselineMissingError} for those — callers should
* fall back to a placeholder synthesis (see `@mochi.js/core.launch`'s
* `synthesizePlaceholderProfile` for the pattern).
*/
export function getProfile(_id: ProfileId): never {
throw new Error(
"@mochi.js/profiles.getProfile is not yet implemented (v0.0.1 claim). " +
"Lands in phase 0.4; see PLAN.md §12.",
);
const PROFILES_WITH_CAPTURED_BASELINE: ReadonlySet<ProfileId> = new Set([
"mac-m4-chrome-stable",
"mac-chrome-stable",
"mac-chrome-beta",
"linux-chrome-stable",
"mac-brave-stable",
"windows-chrome-stable",
]);
/** Thrown when `id` isn't in {@link KNOWN_PROFILE_IDS} at all. */
export class UnknownProfileIdError extends Error {
override readonly name = "UnknownProfileIdError";
readonly id: string;
constructor(id: string) {
super(
`@mochi.js/profiles: unknown profile id "${id}". ` +
`Expected one of: ${KNOWN_PROFILE_IDS.join(", ")}.`,
);
this.id = id;
}
}
/**
* Thrown when `id` is a known catalog entry but no captured baseline
* (`data/<id>/profile.json`) ships in the package — typically a
* declared-but-not-yet-captured device class. Callers may catch this
* and fall back to a synthesized placeholder profile.
*/
export class ProfileBaselineMissingError extends Error {
override readonly name = "ProfileBaselineMissingError";
readonly id: ProfileId;
constructor(id: ProfileId) {
super(
`@mochi.js/profiles: profile "${id}" is declared in KNOWN_PROFILE_IDS ` +
`but no captured baseline ships in the package. ` +
`Profiles with captured baselines: ${[...PROFILES_WITH_CAPTURED_BASELINE].join(", ")}.`,
);
this.id = id;
}
}
/** True when `id` is a known catalog entry. */
function isKnownProfileId(id: string): id is ProfileId {
return (KNOWN_PROFILE_IDS as readonly string[]).includes(id);
}
/**
* True when {@link getProfile} can successfully load `id` (i.e. the id is
* known AND a captured baseline ships). Useful for callers that want to
* decide between the real-baseline path and a placeholder synthesis without
* catching exceptions.
*/
export async function hasProfile(id: string): Promise<boolean> {
if (!isKnownProfileId(id)) return false;
if (!PROFILES_WITH_CAPTURED_BASELINE.has(id)) return false;
return await Bun.file(profilePath(id)).exists();
}
/**
* Resolve a profile by id, loading the captured `data/<id>/profile.json`
* baseline that ships with this package.
*
* Throws:
* - {@link UnknownProfileIdError} if `id` isn't in {@link KNOWN_PROFILE_IDS}.
* - {@link ProfileBaselineMissingError} if `id` is known but no baseline
* ships in the package — callers may fall back to a placeholder.
*/
export async function getProfile(id: ProfileId): Promise<ProfileV1> {
if (!isKnownProfileId(id)) {
// Defensive: callers using `as ProfileId` may sneak unknown values past
// the type system. Surface a precise error rather than a file-not-found.
throw new UnknownProfileIdError(id);
}
if (!PROFILES_WITH_CAPTURED_BASELINE.has(id)) {
throw new ProfileBaselineMissingError(id);
}
const file = Bun.file(profilePath(id));
if (!(await file.exists())) {
// Inconsistency between the in-source set and the on-disk data —
// surface as the same baseline-missing error so callers' fallback
// logic still kicks in. This shouldn't happen in published builds.
throw new ProfileBaselineMissingError(id);
}
return (await file.json()) as ProfileV1;
}
/**
* Absolute path to a profile's captured `profile.json`. Uses
* `import.meta.dir` so the lookup works both in-source (running from
* `packages/profiles/src/`) and after publish (the `data/` dir ships as a
* sibling of `src/` per the package's `files` array).
*/
function profilePath(id: ProfileId): string {
return join(import.meta.dir, "..", "data", id, "profile.json");
}