@vosjs/cli 0.40.0 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -509,7 +509,7 @@ async function cmdCheck(argv) {
509
509
  return result.ok ? EXIT_OK : EXIT_ERROR;
510
510
  }
511
511
  async function delegate(argv, viaAlias = false) {
512
- const { run } = await import("./run-SDPKU6AV.js");
512
+ const { run } = await import("./run-5PCYT25T.js");
513
513
  if (viaAlias && argv[0]) {
514
514
  process.stderr.write(
515
515
  `note: "vos voila ${argv[0]}" is now "vos ${argv[0]}".
@@ -569,7 +569,7 @@ async function main() {
569
569
  main().then(async (code) => {
570
570
  if (code === EXIT_OK) {
571
571
  const verb = process.argv[2] ?? "";
572
- const { HELP } = await import("./run-SDPKU6AV.js");
572
+ const { HELP } = await import("./run-5PCYT25T.js");
573
573
  const documented = [
574
574
  ...helpFlagsFor(HELP_ENGINE, verb),
575
575
  ...helpFlagsFor(HELP, verb)
package/dist/index.d.ts CHANGED
@@ -215,6 +215,54 @@ interface TakeData {
215
215
  /** Load a take directory; cursor+meta are required, doc/actions optional. */
216
216
  declare function loadTake(dir: string): Promise<TakeData>;
217
217
 
218
+ /**
219
+ * The wall check: did the recorder land where it was asked, or in front of
220
+ * a sign-in? A take of a product behind a login, recorded without a session,
221
+ * used to succeed: the footage was the login page (or wherever the site
222
+ * sends a stranger), and the only symptom was a skipped selector. This says
223
+ * it in words, before a frame is captured and before a re-record clears the
224
+ * footage it would have replaced.
225
+ *
226
+ * Pure: the recorder gathers the evidence, this decides. A heuristic is
227
+ * acceptable because both failure directions are cheap: a false refusal
228
+ * costs one flag (`--allow-wall`), a false pass costs what every such take
229
+ * cost before.
230
+ */
231
+ /** What the recorder saw once the first navigation settled. */
232
+ interface Arrival {
233
+ askedUrl: string;
234
+ landedUrl: string;
235
+ /** HTTP status of the main document, when the navigation produced one. */
236
+ status?: number;
237
+ /** `input[type=password]` fields that are visible on the page. */
238
+ passwordFields: number;
239
+ /** A password field marked `autocomplete="new-password"` (a settings or sign-up form). */
240
+ newPasswordField: boolean;
241
+ /** A visible one-time-code field (`autocomplete="one-time-code"`). */
242
+ oneTimeCodeField: boolean;
243
+ }
244
+ type WallKind =
245
+ /** the asked URL answered 401 or 403 */
246
+ 'status'
247
+ /** landed on an identity provider's host */
248
+ | 'idp'
249
+ /** landed on a sign-in form or a sign-in path */
250
+ | 'signin'
251
+ /** sent somewhere else, with no sign-in in sight (a site that shows strangers a public page) */
252
+ | 'redirect';
253
+ interface WallVerdict {
254
+ kind: WallKind;
255
+ /**
256
+ * `hard` is refused always; `soft` is refused under `--strict` and said as
257
+ * a warning otherwise, because a redirect alone is not proof of a wall.
258
+ */
259
+ level: 'hard' | 'soft';
260
+ /** origin + path, never the query or hash (they can carry tokens). */
261
+ asked: string;
262
+ landed: string;
263
+ message: string;
264
+ }
265
+
218
266
  interface FrameRec {
219
267
  file: string;
220
268
  /** ms since t0 */
@@ -243,6 +291,8 @@ interface RecordResult {
243
291
  skipped: SkippedStep[];
244
292
  /** the initial goto never reached networkidle (recording proceeded anyway). */
245
293
  navTimeout: boolean;
294
+ /** A wall the caller let through; null when the recorder landed where it was asked. */
295
+ wall: WallVerdict | null;
246
296
  /**
247
297
  * Smoothness telemetry: stretches ≥400ms with no visual change. Frozen
248
298
  * footage is the #1 enemy of a smooth product video — either the flow should
@@ -275,6 +325,13 @@ interface RecordOpts {
275
325
  * timeout, so a miss here is a miss in the take.
276
326
  */
277
327
  dryRun?: boolean;
328
+ /**
329
+ * Called once the first navigation has settled, BEFORE a frame is captured.
330
+ * The caller judges the wall here and only then prepares the take
331
+ * directory, so a take refused at a sign-in never clears the footage a
332
+ * re-record would have replaced. A throw closes the context and propagates.
333
+ */
334
+ onArrival?: (arrival: Arrival) => Promise<WallVerdict | null | void> | WallVerdict | null | void;
278
335
  }
279
336
  declare function recordTake(browser: Browser, url: string, actions: ActionsFile, paths: TakePaths, log: (msg: string) => void, opts?: RecordOpts): Promise<RecordResult>;
280
337
 
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ import {
30
30
  validateActions,
31
31
  waitForPageDone,
32
32
  writeSyncState
33
- } from "./chunk-7TDL3N24.js";
33
+ } from "./chunk-BD4FXBUO.js";
34
34
  import {
35
35
  BrowserUnavailableError,
36
36
  configDuration,
@@ -4,7 +4,7 @@ import {
4
4
  MULTI_FLAGS,
5
5
  run,
6
6
  takeBrowserArgs
7
- } from "./chunk-7TDL3N24.js";
7
+ } from "./chunk-BD4FXBUO.js";
8
8
  import "./chunk-FACYY7VV.js";
9
9
  export {
10
10
  HELP,
@@ -12,4 +12,4 @@ export {
12
12
  run,
13
13
  takeBrowserArgs
14
14
  };
15
- //# sourceMappingURL=run-SDPKU6AV.js.map
15
+ //# sourceMappingURL=run-5PCYT25T.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vosjs/cli",
3
- "version": "0.40.0",
3
+ "version": "0.41.0",
4
4
  "description": "The vos CLI: record the real product from a scripted browser flow, auto-zoom from the cursor track, cut as data in doc.json, render deterministic video and stills, deliver a release's media per destination spec, and sync with vos.so. One binary, every verb, MIT.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -49,11 +49,11 @@
49
49
  "mediabunny": "^1.55.7",
50
50
  "playwright": "^1.49.0",
51
51
  "@vosjs/core": "^0.25.0",
52
- "@vosjs/render-core": "^0.2.8",
52
+ "@vosjs/editor": "^1.3.1",
53
53
  "@vosjs/elements": "^0.8.1",
54
54
  "@vosjs/shared": "^0.4.1",
55
- "@vosjs/editor": "^1.3.1",
56
- "@vosjs/studio-core": "^0.27.0",
55
+ "@vosjs/render-core": "^0.2.8",
56
+ "@vosjs/studio-core": "^0.28.0",
57
57
  "@vosjs/tween": "^0.8.2",
58
58
  "@vosjs/timeline": "^0.4.1"
59
59
  },
@@ -45,7 +45,19 @@
45
45
  "type": "boolean",
46
46
  "description": "false = browser-recorder take: moments are head/tail/scenes only"
47
47
  },
48
- "windowFocusedFrac": { "type": ["number", "null"] }
48
+ "windowFocusedFrac": { "type": ["number", "null"] },
49
+ "wall": {
50
+ "type": ["object", "null"],
51
+ "description": "the recorder did not land where it was asked (a sign-in, an identity provider, a 401/403, a redirect elsewhere) and the take was recorded anyway: the footage may be the wrong page. `asked`/`landed` are origin + path. null = it landed where it was asked, or the recorder does not check",
52
+ "properties": {
53
+ "kind": {
54
+ "type": "string",
55
+ "enum": ["status", "idp", "signin", "redirect"]
56
+ },
57
+ "asked": { "type": "string" },
58
+ "landed": { "type": "string" }
59
+ }
60
+ }
49
61
  }
50
62
  },
51
63
  "units": {