feat(06-08): the ?drive= fixture-replay knob — the D-16 browser leg's fix source

- ?drive=<name> replaces navigator.geolocation with a replay source
  streaming a committed drive fixture (web/test/fixtures/drives/*.json)
  through the LIVE shell: the real pump arms the real
  createGuidanceWatch against it — no test-only bypass of validation
- the replay clock starts lazily at the first watchPosition arm (the
  route draw — nothing emitted before a consumer exists) and plays
  REAL-TIME: the machine's grace/storm clocks read wall time
- window.__ARAHARAH_DRIVE = { pause(), resume(), name }: pause freezes
  emission mid-stream (the capture legs' freeze for scripted taps and
  the REROUTING window), resume continues; the machine's wall clock
  keeps running across a pause (documented harness semantics)
- unknown drive name -> one honest token (ARAHARAH-DRIVE
  state=unknown) + the default geolocation stays — never a crash,
  never arbitrary data (T-06-08 Tampering mitigation); slug guard on
  the name, defensive fixture shape check
- import.meta.glob pattern is ROOT-ABSOLUTE (/test/fixtures/drives/*.json
  — Vite 8's importGlob matches no relative pattern escaping src/,
  verified by the dev-server probe); fixtures inline into the harness
  bundle only — production tree-shake verified clean in BOTH directions
- BA5 posture held: production scan clean, harness bundle carries the
  replay; 147/147 web tests, typecheck clean
This commit is contained in:
araharah-executor
2026-10-24 21:06:17 +08:00
parent fca2a904d0
commit d0d5a7dc27
2 changed files with 219 additions and 1 deletions
+1 -1
View File
@@ -9,7 +9,7 @@
<body> <body>
<div id="app"></div> <div id="app"></div>
<script type="module"> <script type="module">
/* D-11 Mock-Telegram profile: ?mock=android|ios|tdesktop|macos|web + ?scheme=light|dark + ?pin=1 + ?locale=en|ms + ?fixdelay + ?sessiondelay + ?dest=<id> + ?fixpair=<pair-id> /* D-11 Mock-Telegram profile: ?mock=android|ios|tdesktop|macos|web + ?scheme=light|dark + ?pin=1 + ?locale=en|ms + ?fixdelay + ?sessiondelay + ?dest=<id> + ?fixpair=<pair-id> + ?drive=<fixture-name> (06-08: the drive replay is read inside the mock module — installMockWebApp replaces navigator.geolocation with the committed fixture's stream)
Harness-only: served from web/dist-harness, never deployed. Harness-only: served from web/dist-harness, never deployed.
The WHOLE block below is inside `if (__ARAHARAH_HARNESS__)` — Vite's `define` The WHOLE block below is inside `if (__ARAHARAH_HARNESS__)` — Vite's `define`
replaces that identifier with `false` in the production build, so the branch is replaces that identifier with `false` in the production build, so the branch is
+218
View File
@@ -29,6 +29,25 @@
* tests read (the `__events` / `__backButtonClicks` exposure precedent). * tests read (the `__events` / `__backButtonClicks` exposure precedent).
* The mock's initData is HMAC-unvalidated by design — the runner page * The mock's initData is HMAC-unvalidated by design — the runner page
* stubs `/api/session`. * stubs `/api/session`.
*
* The ?drive= replay knob (06-08, D-16's browser leg): `?drive=<name>` makes
* THIS mock replace navigator.geolocation with a replay source that streams
* a committed drive fixture (web/test/fixtures/drives/*.json — the same JSON
* the Node replays prove the brain with) through the LIVE shell — the real
* pump, real builders, real camera consume the fixes via the real
* createGuidanceWatch. The replay clock starts lazily at the FIRST
* watchPosition arm (the route draw — the pump's ensureWatch), so no fix is
* ever emitted before something consumes it, and plays REAL-TIME: the
* machine's grace/storm clocks read wall time (route.ts's now()), so a
* compressed playback would desync them. window.__ARAHARAH_DRIVE.pause()/
* resume() freeze/resume emission mid-stream — the capture script's freeze
* for stable scripted taps (confirm/tripend legs) and the REROUTING leg's
* window. A pause stops EMISSION only; the shell's wall clock keeps running
* (grace windows inflate across a pause — legs that pause close before any
* machine timing matters). Console emits NOTHING per fix; an unknown drive
* name is the knob's one honest token (`ARAHARAH-DRIVE state=unknown`) and
* falls back to the default geolocation — never a crash, never replayed
* arbitrary data (the fixture/kernel mismatch mitigation, T-06-08).
*/ */
import type { TelegramWebAppLike, HomeScreenStatus } from "../telegram/webapp.ts"; import type { TelegramWebAppLike, HomeScreenStatus } from "../telegram/webapp.ts";
@@ -162,6 +181,189 @@ function buildMockInitData(languageCode?: string, startParam?: string | null): s
return startParam ? `${base}&start_param=${encodeURIComponent(startParam)}` : base; return startParam ? `${base}&start_param=${encodeURIComponent(startParam)}` : base;
} }
/* ————— the ?drive= fixture-replay source (06-08, D-16's browser leg) ————— */
/** A committed drive fixture's structural minimum (the 06-02 replay shape:
* { _notice, pairId, maneuverIdx, kinds, fixes[] } with Fix-shaped fixes). */
interface DriveFixture {
fixes: Array<{ lat: number; lng: number; accuracyM?: number | null; headingDeg?: number | null; ts: number; source?: string }>;
}
/** The pause/resume surface the capture script drives (window.__ARAHARAH_DRIVE). */
export interface DriveReplayControls {
/** Freeze the replay clock mid-stream — emission stops until resume(). */
pause(): void;
/** Continue mid-stream: unpaused wall time resumes driving the schedule. */
resume(): void;
readonly name: string;
}
declare global {
interface Window {
/** Installed ONLY when ?drive= names a committed fixture — the capture
* script's freeze surface (and its diagnostics: .name). */
__ARAHARAH_DRIVE?: DriveReplayControls;
}
}
/** Drive names are slugs (the pairId/destinationId pattern — bounds the
* lookup against hostile query strings before the fixture record is read). */
const DRIVE_NAME_PATTERN = /^[a-z0-9-]{1,64}$/;
/** The committed D-16 drive replays, inlined into the HARNESS bundle at build
* time (eager glob, the route-profiles BA-exclusion posture: this module is
* imported by main.ts's dead harness branch and tree-shaken from production —
* BA5 asserts the absence). The pattern is ROOT-ABSOLUTE (/test/... — Vite 8's
* importGlob matches no relative pattern that escapes src/; verified by the
* 06-08 dev-server probe). */
const DRIVE_FIXTURES = import.meta.glob<unknown>("/test/fixtures/drives/*.json", {
eager: true,
import: "default",
});
/** Defensive shape check (the fixture-source isUsablePair posture): a
* malformed drive degrades to the honest unknown-fallback, never a crash
* and never a partial replay (T-06-08's Tampering mitigation). */
function isDriveFixture(value: unknown): value is DriveFixture {
if (value === null || typeof value !== "object") return false;
const fixes = (value as { fixes?: unknown }).fixes;
if (!Array.isArray(fixes) || fixes.length < 2) return false;
return fixes.every((f) => {
if (f === null || typeof f !== "object") return false;
const p = f as { lat?: unknown; lng?: unknown; ts?: unknown };
return (
typeof p.lat === "number" &&
Number.isFinite(p.lat) &&
typeof p.lng === "number" &&
Number.isFinite(p.lng) &&
typeof p.ts === "number" &&
Number.isFinite(p.ts)
);
});
}
function driveFixtureByName(name: string): DriveFixture | null {
if (!DRIVE_NAME_PATTERN.test(name)) return null;
const hit = DRIVE_FIXTURES[`/test/fixtures/drives/${name}.json`];
return isDriveFixture(hit) ? hit : null;
}
/** Position assembled from a fixture fix at a replayed wall timestamp. The
* watch (createGuidanceWatch) normalizes exactly the four consumed fields;
* the GeolocationPosition type's remaining members are cast — the harness
* source is the fixture itself, not a lying platform. */
function replayedPosition(f: DriveFixture["fixes"][number], timestamp: number): GeolocationPosition {
return {
coords: {
latitude: f.lat,
longitude: f.lng,
accuracy: f.accuracyM ?? undefined,
altitude: null,
altitudeAccuracy: null,
altitudeAngle: null,
heading: f.headingDeg ?? undefined,
speed: null,
},
timestamp,
} as unknown as GeolocationPosition;
}
/**
* Replace navigator.geolocation with the drive replay (harness-only): the
* REAL pump arms its REAL watch against this object, so the shell consumes
* the committed stream through the unmodified D-15 throttle — replay proves
* the shell, never bypassing it (the trust boundary's law).
*
* Clock semantics: the schedule is real-time (offset = fix.ts − fixes[0].ts;
* a 200ms tick delivers every fix whose offset has elapsed). pos.timestamp
* is t0 + offset so the machine's now()-anchored windows stay aligned with
* the fixes that drive them. Exhaustion stops the timer; a later re-arm
* delivers nothing (the drive is over).
*/
function installDriveReplay(name: string, fixture: DriveFixture): DriveReplayControls {
const fixes = fixture.fixes;
const first = fixes[0]!;
const offsets = fixes.map((f) => Math.max(0, f.ts - first.ts));
let clockStart: number | null = null; // performance.now() at the first watch arm
let wallT0 = 0; // Date.now() at the same instant — pos.timestamp = wallT0 + offset
let pausedAt: number | null = null;
let pausedTotal = 0;
let delivered = 0;
let nextId = 0;
let timer: ReturnType<typeof setInterval> | null = null;
const sinks = new Map<number, (pos: GeolocationPosition) => void>();
const elapsedMs = (): number => {
if (clockStart === null) return -1;
const nowP = performance.now();
return (nowP - clockStart) - pausedTotal - (pausedAt !== null ? nowP - pausedAt : 0);
};
const stopTimer = (): void => {
if (timer !== null) {
clearInterval(timer);
timer = null;
}
};
const tick = (): void => {
const e = elapsedMs();
if (e < 0) return;
while (delivered < fixes.length) {
const offset = offsets[delivered]!;
if (offset > e) break;
const fix = fixes[delivered]!;
const pos = replayedPosition(fix, wallT0 + offset);
for (const sink of sinks.values()) sink(pos);
delivered += 1;
}
if (delivered >= fixes.length) stopTimer(); // fully replayed — the drive is over
};
const ensureTimer = (): void => {
if (timer === null && delivered < fixes.length) timer = setInterval(tick, 200);
};
const fakeGeo = {
getCurrentPosition(success: PositionCallback, _error?: PositionErrorCallback | null, _opts?: PositionOptions): void {
// the chain's LINK-2 shape (unused while the Telegram mock serves LINK 1):
// the drive's FIRST fix, at wall-now, like a real one-shot read
const f = first;
setTimeout(() => success(replayedPosition(f, Date.now())), 0);
},
watchPosition(success: PositionCallback, _error?: PositionErrorCallback | null, _opts?: PositionOptions): number {
const id = ++nextId;
sinks.set(id, success);
if (clockStart === null) {
clockStart = performance.now();
wallT0 = Date.now();
}
ensureTimer(); // the first arm starts the clock; re-arms resume delivery
return id;
},
clearWatch(id: number): void {
sinks.delete(id);
if (sinks.size === 0) stopTimer(); // the pump stopped the watch — the replay stops with it
},
};
Object.defineProperty(navigator, "geolocation", { value: fakeGeo, configurable: true });
const controls: DriveReplayControls = {
get name(): string {
return name;
},
pause(): void {
if (pausedAt === null) pausedAt = performance.now();
},
resume(): void {
if (pausedAt !== null) {
pausedTotal += performance.now() - pausedAt;
pausedAt = null;
}
ensureTimer();
},
};
window.__ARAHARAH_DRIVE = controls;
return controls;
}
export function installMockWebApp(options: MockOptions = {}): TelegramWebAppLike { export function installMockWebApp(options: MockOptions = {}): TelegramWebAppLike {
const version = options.version ?? "8.0"; const version = options.version ?? "8.0";
const telegramFix = options.telegramFix ?? null; const telegramFix = options.telegramFix ?? null;
@@ -250,6 +452,22 @@ export function installMockWebApp(options: MockOptions = {}): TelegramWebAppLike
installed = fake; installed = fake;
const w = window as unknown as { Telegram?: unknown }; const w = window as unknown as { Telegram?: unknown };
w.Telegram = { WebApp: fake }; w.Telegram = { WebApp: fake };
// The ?drive= replay knob (06-08): read from location.search HERE — the
// mock module is the harness surface, so the knob rides every install path
// (the runner page's profile install AND main.ts's plain-dev fallback)
// without a new carrier. Unknown name → one honest token + the default
// geolocation stays; never a crash, never replayed arbitrary data.
let driveName: string | null = null;
try {
driveName = new URLSearchParams(window.location?.search ?? "").get("drive");
} catch {
driveName = null;
}
if (driveName !== null) {
const fixture = driveFixtureByName(driveName);
if (fixture === null) console.log("ARAHARAH-DRIVE state=unknown");
else installDriveReplay(driveName, fixture);
}
return fake; return fake;
} }