@vosjs/cli 0.41.1 → 0.42.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/README.md +13 -0
- package/dist/{chunk-4QVEV3HX.js → chunk-7RMULTDM.js} +270 -11
- package/dist/chunk-7RMULTDM.js.map +1 -0
- package/dist/cli.js +3 -3
- package/dist/index.d.ts +43 -0
- package/dist/index.js +1 -1
- package/dist/{run-ZIOIU3SD.js → run-WN2IO3WL.js} +2 -2
- package/package.json +5 -5
- package/schema/actions.schema.json +22 -0
- package/schema/digest.schema.json +22 -0
- package/dist/chunk-4QVEV3HX.js.map +0 -1
- /package/dist/{run-ZIOIU3SD.js.map → run-WN2IO3WL.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -511,7 +511,7 @@ async function cmdCheck(argv) {
|
|
|
511
511
|
return result.ok ? EXIT_OK : EXIT_ERROR;
|
|
512
512
|
}
|
|
513
513
|
async function delegate(argv, viaAlias = false) {
|
|
514
|
-
const { run } = await import("./run-
|
|
514
|
+
const { run } = await import("./run-WN2IO3WL.js");
|
|
515
515
|
if (viaAlias && argv[0]) {
|
|
516
516
|
process.stderr.write(
|
|
517
517
|
`note: "vos voila ${argv[0]}" is now "vos ${argv[0]}".
|
|
@@ -551,7 +551,7 @@ async function main() {
|
|
|
551
551
|
const engine = HELP_ENGINE.split("\n").filter(
|
|
552
552
|
(l) => l.startsWith(` vos ${cmd} `)
|
|
553
553
|
);
|
|
554
|
-
const { verbHelp } = await import("./run-
|
|
554
|
+
const { verbHelp } = await import("./run-WN2IO3WL.js");
|
|
555
555
|
const take = verbHelp(cmd);
|
|
556
556
|
process.stdout.write(
|
|
557
557
|
`${engine.join("\n")}
|
|
@@ -583,7 +583,7 @@ ${take.includes("no such verb") ? "" : take}`
|
|
|
583
583
|
main().then(async (code) => {
|
|
584
584
|
if (code === EXIT_OK) {
|
|
585
585
|
const verb = process.argv[2] ?? "";
|
|
586
|
-
const { HELP } = await import("./run-
|
|
586
|
+
const { HELP } = await import("./run-WN2IO3WL.js");
|
|
587
587
|
const documented = [
|
|
588
588
|
...helpFlagsFor(HELP_ENGINE, verb),
|
|
589
589
|
...helpFlagsFor(HELP, verb)
|
package/dist/index.d.ts
CHANGED
|
@@ -110,6 +110,37 @@ interface PaceReport {
|
|
|
110
110
|
}[];
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* What a signed-in take SHOWS. Getting past the login is half the problem;
|
|
115
|
+
* the other half is that the account's own data is now in the frame: an
|
|
116
|
+
* email address in the header, a key on a settings page, a card number.
|
|
117
|
+
* Asking nicely does not hold this line (a person asked to sign in with a
|
|
118
|
+
* demo account signs in as themselves, because it is the account they have),
|
|
119
|
+
* so the recorder looks.
|
|
120
|
+
*
|
|
121
|
+
* Two pieces, both run IN the page:
|
|
122
|
+
*
|
|
123
|
+
* - the EXPOSURE scan reads the text that is visible in the viewport after
|
|
124
|
+
* each step and reports the KIND of thing it saw and where. Never the
|
|
125
|
+
* string itself: a report that quotes the secret is a second leak.
|
|
126
|
+
* - a MASK hides a selector before the first frame is captured and keeps it
|
|
127
|
+
* hidden across navigations and re-renders, so the real value is never in
|
|
128
|
+
* a frame, never in the recording, never pushed. `as: 'text'` swaps the
|
|
129
|
+
* words (a product reads better than a redaction); `as: 'blur'` blurs.
|
|
130
|
+
*
|
|
131
|
+
* The matchers are ONE plain-JavaScript source string, evaluated in the page
|
|
132
|
+
* and, by the tests, in Node: a function serialized out of a bundle picks up
|
|
133
|
+
* the bundler's `__name` helper and dies in the page, and two copies of a
|
|
134
|
+
* regex drift.
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
interface MaskRule {
|
|
138
|
+
selector: string;
|
|
139
|
+
/** `blur` (default) blurs the element; `text` swaps its words for `text`. */
|
|
140
|
+
as?: 'blur' | 'text';
|
|
141
|
+
text?: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
113
144
|
/**
|
|
114
145
|
* The action script — the declarative recipe an agent (or human) writes to
|
|
115
146
|
* drive a take. Small on purpose: selectors + a handful of verbs. The recorder
|
|
@@ -124,6 +155,14 @@ interface ActionsFile {
|
|
|
124
155
|
width: number;
|
|
125
156
|
height: number;
|
|
126
157
|
};
|
|
158
|
+
/**
|
|
159
|
+
* Hidden BEFORE the first frame is captured and kept hidden across
|
|
160
|
+
* navigations: what a signed-in account shows that must not ship. `blur`
|
|
161
|
+
* (default) blurs the element; `text` swaps its words for `text`, which is
|
|
162
|
+
* for IDENTIFIERS (an email, a name, an account id), never for product
|
|
163
|
+
* copy or numbers: the video must stay true to the product.
|
|
164
|
+
*/
|
|
165
|
+
mask?: MaskRule[];
|
|
127
166
|
steps: ActionStep[];
|
|
128
167
|
}
|
|
129
168
|
type ActionStep = ({
|
|
@@ -293,6 +332,10 @@ interface RecordResult {
|
|
|
293
332
|
navTimeout: boolean;
|
|
294
333
|
/** A wall the caller let through; null when the recorder landed where it was asked. */
|
|
295
334
|
wall: WallVerdict | null;
|
|
335
|
+
/** Sensitive-looking text seen in the frame (kind + place, never the string). */
|
|
336
|
+
exposures: NonNullable<RecordingMeta['exposures']>;
|
|
337
|
+
/** The script's masks with how many elements each reached; hits 0 hid nothing. */
|
|
338
|
+
masks: NonNullable<RecordingMeta['masks']>;
|
|
296
339
|
/**
|
|
297
340
|
* Smoothness telemetry: stretches ≥400ms with no visual change. Frozen
|
|
298
341
|
* footage is the #1 enemy of a smooth product video — either the flow should
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
run,
|
|
6
6
|
takeBrowserArgs,
|
|
7
7
|
verbHelp
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-7RMULTDM.js";
|
|
9
9
|
import "./chunk-FACYY7VV.js";
|
|
10
10
|
export {
|
|
11
11
|
HELP,
|
|
@@ -14,4 +14,4 @@ export {
|
|
|
14
14
|
takeBrowserArgs,
|
|
15
15
|
verbHelp
|
|
16
16
|
};
|
|
17
|
-
//# sourceMappingURL=run-
|
|
17
|
+
//# sourceMappingURL=run-WN2IO3WL.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vosjs/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.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",
|
|
@@ -48,14 +48,14 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"mediabunny": "^1.55.7",
|
|
50
50
|
"playwright": "^1.49.0",
|
|
51
|
-
"@vosjs/editor": "^1.3.1",
|
|
52
|
-
"@vosjs/elements": "^0.8.1",
|
|
53
51
|
"@vosjs/core": "^0.25.0",
|
|
54
|
-
"@vosjs/
|
|
52
|
+
"@vosjs/elements": "^0.8.1",
|
|
55
53
|
"@vosjs/render-core": "^0.2.8",
|
|
54
|
+
"@vosjs/shared": "^0.4.1",
|
|
55
|
+
"@vosjs/editor": "^1.3.1",
|
|
56
56
|
"@vosjs/timeline": "^0.4.1",
|
|
57
57
|
"@vosjs/tween": "^0.8.2",
|
|
58
|
-
"@vosjs/studio-core": "^0.
|
|
58
|
+
"@vosjs/studio-core": "^0.29.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/node": "^22",
|
|
@@ -29,6 +29,28 @@
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
|
+
"mask": {
|
|
33
|
+
"type": "array",
|
|
34
|
+
"description": "Hidden BEFORE the first frame is captured and kept hidden across navigations and re-renders: what a signed-in account shows that must not ship. The real value is never in a frame, never in the recording, never pushed. `vos record` reports what it still sees afterwards (meta.exposures), and a mask whose selector reached nothing fails --strict.",
|
|
35
|
+
"items": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"required": ["selector"],
|
|
38
|
+
"additionalProperties": false,
|
|
39
|
+
"properties": {
|
|
40
|
+
"selector": { "type": "string" },
|
|
41
|
+
"as": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"enum": ["blur", "text"],
|
|
44
|
+
"default": "blur",
|
|
45
|
+
"description": "blur the element, or swap its words for `text`. A form control is always blurred: writing into an input would change what the app submits. `text` is for IDENTIFIERS (an email, a name, an account id), never for product copy or numbers."
|
|
46
|
+
},
|
|
47
|
+
"text": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"description": "shown instead, with as: \"text\""
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
32
54
|
"steps": {
|
|
33
55
|
"type": "array",
|
|
34
56
|
"minItems": 1,
|
|
@@ -46,6 +46,28 @@
|
|
|
46
46
|
"description": "false = browser-recorder take: moments are head/tail/scenes only"
|
|
47
47
|
},
|
|
48
48
|
"windowFocusedFrac": { "type": ["number", "null"] },
|
|
49
|
+
"exposures": {
|
|
50
|
+
"type": "array",
|
|
51
|
+
"description": "sensitive-looking text the recorder saw IN the frame: the KIND and the place, never the string. Listed once each, at the first step it was visible (step -1 = as the page opened). `rect` is viewport CSS px. Look at those frames before the take goes anywhere; the fix is a demo account or a `mask` in actions.json and a re-record",
|
|
52
|
+
"items": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"properties": {
|
|
55
|
+
"step": { "type": "integer" },
|
|
56
|
+
"kind": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"enum": ["email", "key", "card", "card-tail"]
|
|
59
|
+
},
|
|
60
|
+
"selector": { "type": "string" },
|
|
61
|
+
"rect": { "type": "object" },
|
|
62
|
+
"seen": { "type": "integer" }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"masks": {
|
|
67
|
+
"type": "array",
|
|
68
|
+
"description": "what the script hid before the camera rolled, with how many elements each selector reached; hits 0 hid nothing",
|
|
69
|
+
"items": { "type": "object" }
|
|
70
|
+
},
|
|
49
71
|
"wall": {
|
|
50
72
|
"type": ["object", "null"],
|
|
51
73
|
"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",
|