kaloko 0.3.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 +119 -0
- package/bin/kaloko.mjs +4 -0
- package/bin/qawalk.mjs +4 -0
- package/package.json +42 -0
- package/schemas/bundle.v1.json +19 -0
- package/schemas/config.v1.json +268 -0
- package/schemas/revision.v1.json +36 -0
- package/schemas/run.v1.json +549 -0
- package/schemas/scenario.v1.json +668 -0
- package/schemas/tokens.v1.json +102 -0
- package/skills/kaloko/SKILL.md +94 -0
- package/skills/kaloko/reference/acceptance.md +208 -0
- package/skills/kaloko/reference/apps.md +161 -0
- package/skills/kaloko/reference/collaboration.md +218 -0
- package/skills/kaloko/reference/design.md +143 -0
- package/skills/kaloko/reference/documentation.md +72 -0
- package/skills/kaloko/reference/environments.md +140 -0
- package/skills/kaloko/reference/evaluation.md +62 -0
- package/skills/kaloko/reference/execution.md +75 -0
- package/skills/kaloko/reference/mcp.md +69 -0
- package/skills/kaloko/reference/stacks.md +122 -0
- package/src/cli.mjs +1344 -0
- package/src/lib/access.mjs +169 -0
- package/src/lib/apps/capture.mjs +59 -0
- package/src/lib/apps/drivers.mjs +284 -0
- package/src/lib/apps/helper.swift +102 -0
- package/src/lib/apps/tree.mjs +222 -0
- package/src/lib/browser-daemon.mjs +41 -0
- package/src/lib/browser.mjs +161 -0
- package/src/lib/build.mjs +149 -0
- package/src/lib/calibrate.mjs +97 -0
- package/src/lib/capture.mjs +233 -0
- package/src/lib/compare.mjs +88 -0
- package/src/lib/config.mjs +117 -0
- package/src/lib/console.mjs +13 -0
- package/src/lib/coverage.mjs +75 -0
- package/src/lib/design-cli.mjs +440 -0
- package/src/lib/design-core.mjs +163 -0
- package/src/lib/design.mjs +164 -0
- package/src/lib/doctor.mjs +149 -0
- package/src/lib/draft.mjs +76 -0
- package/src/lib/drift.mjs +145 -0
- package/src/lib/evaluate.mjs +222 -0
- package/src/lib/git.mjs +70 -0
- package/src/lib/htmlview.mjs +130 -0
- package/src/lib/jev.mjs +95 -0
- package/src/lib/mail.mjs +182 -0
- package/src/lib/manifest-core.mjs +127 -0
- package/src/lib/pack-help.mjs +55 -0
- package/src/lib/packs.mjs +121 -0
- package/src/lib/pr.mjs +78 -0
- package/src/lib/probe.mjs +379 -0
- package/src/lib/recheck.mjs +70 -0
- package/src/lib/run.mjs +85 -0
- package/src/lib/scenario.mjs +98 -0
- package/src/lib/schema.mjs +25 -0
- package/src/lib/secrets.mjs +59 -0
- package/src/lib/service.mjs +52 -0
- package/src/lib/stack.mjs +130 -0
- package/src/lib/tokens.mjs +352 -0
- package/src/lib/util.mjs +97 -0
- package/templates/ACCEPTANCE.md +55 -0
- package/templates/cs/ACCEPTANCE.md +55 -0
- package/templates/kaloko.config.yml +76 -0
- package/templates/mail/letter-opener.mjs +47 -0
- package/templates/scenario.yml +119 -0
- package/templates/steps/consent.mjs +33 -0
- package/viewer/index.html +2772 -0
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Kaloko
|
|
2
|
+
|
|
3
|
+
Acceptance QA walkthroughs rendered as a shareable flow canvas.
|
|
4
|
+
|
|
5
|
+
Your coding agent (Claude Code, Codex or any LLM with a shell) runs QA from
|
|
6
|
+
your acceptance plan with the `kaloko` skill. Kaloko captures every screen and
|
|
7
|
+
e-mail of the flow, checks the criteria and builds a canvas that shows the
|
|
8
|
+
whole flow (screens, branches, locales, evidence) for review, sign-off and
|
|
9
|
+
living documentation.
|
|
10
|
+
|
|
11
|
+
- Product and guides: <https://kaloko.app>
|
|
12
|
+
- Service (organizations, shared canvases, reviews): <https://kaloko.app>
|
|
13
|
+
|
|
14
|
+
Kaloko also walks **native apps**: Android over adb, the iOS Simulator,
|
|
15
|
+
Electron and macOS apps. Screens taken by any other tool (Maestro, Appium,
|
|
16
|
+
XCUITest) are imported with their UI tree. See the `apps` reference of the
|
|
17
|
+
skill.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
Requires Node 20 or newer.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install --save-dev kaloko
|
|
25
|
+
npx kaloko init --agent claude --org <your-org> # or --agent codex | all
|
|
26
|
+
npx kaloko doctor
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`init` creates `kaloko.config.yml` and copies the `kaloko` skill to
|
|
30
|
+
`.claude/skills/kaloko` (Claude Code) or `skills/kaloko` (Codex). Run it again
|
|
31
|
+
after `npm update kaloko` to refresh the skill.
|
|
32
|
+
|
|
33
|
+
## Then ask your agent
|
|
34
|
+
|
|
35
|
+
With the skill installed you do not type the commands below; the agent does.
|
|
36
|
+
It writes the acceptance plan and the scenario from the task, walks the
|
|
37
|
+
screens, evaluates, shares the canvas and later processes reviewers' feedback.
|
|
38
|
+
For example:
|
|
39
|
+
|
|
40
|
+
> Read the task in docs/tasks/TASK-123, write its acceptance plan and a Kaloko
|
|
41
|
+
> scenario, walk it on local and share the result on the pull request.
|
|
42
|
+
|
|
43
|
+
> Go through the open Kaloko feedback on TASK-123: fix what reviewers
|
|
44
|
+
> rejected, run the affected steps again, share, and answer each comment with
|
|
45
|
+
> what changed.
|
|
46
|
+
|
|
47
|
+
> Draft a Kaloko scenario for https://example.com (home, pricing, contact)
|
|
48
|
+
> with the seo, a11y and perf packs, run it on production read-only and
|
|
49
|
+
> summarise what fails.
|
|
50
|
+
|
|
51
|
+
## Run a scenario by hand (or in CI)
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx kaloko validate qa/flows/checkout.yml
|
|
55
|
+
npx kaloko start --scenario qa/flows/checkout.yml --env local
|
|
56
|
+
npx kaloko browser start
|
|
57
|
+
npx kaloko walk # playwright steps
|
|
58
|
+
npx kaloko capture --step <id> # agent or manual steps
|
|
59
|
+
npx kaloko evaluate # deterministic checks + semantic evaluator
|
|
60
|
+
npx kaloko preview # local canvas
|
|
61
|
+
npx kaloko share --pr # upload to kaloko.app, comment on the PR
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`npx kaloko help` lists every command. When something does not work (Chrome,
|
|
65
|
+
token, environment URL, evaluator key), `npx kaloko doctor` says what to fix.
|
|
66
|
+
|
|
67
|
+
## Design (Kaloko Design)
|
|
68
|
+
|
|
69
|
+
Design the screens of a flow as live HTML with your own agent and skills, in the same scenario development and
|
|
70
|
+
QA use. A design environment (`kind: design`, a folder of steps) is walked and synced into a shared draft the
|
|
71
|
+
team sees live; `kaloko share` there publishes a version of the flow (unchanged steps are stored once). An
|
|
72
|
+
accepted version becomes the design reference, and `packs: [design]` checks every implementation run against
|
|
73
|
+
it (pixels, structure, tokens, contrast). See `skills/kaloko/reference/design.md`, `docs/GLOSSARY.md` and
|
|
74
|
+
`docs/SURFACES.md`.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npx kaloko start --scenario qa/flows/checkout.yml --env design
|
|
78
|
+
npx kaloko walk && npx kaloko sync # only changed steps render and travel
|
|
79
|
+
npx kaloko share --name "Checkout v2" # a version of the whole flow
|
|
80
|
+
npx kaloko reference --design --version 2 # after the team accepted it
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Configuration and secrets
|
|
84
|
+
|
|
85
|
+
Project configuration is `kaloko.config.yml` in the repository root:
|
|
86
|
+
environments, readonly rules for production, browser, mailbox and evaluator.
|
|
87
|
+
`npx kaloko init` writes a commented template.
|
|
88
|
+
|
|
89
|
+
Secrets are never written in the config. Wherever a secret is needed, the
|
|
90
|
+
config names an environment variable of your choice (`password_env:
|
|
91
|
+
STAGING_PASSWORD`, `{ env: CF_ACCESS_CLIENT_SECRET }`). Values are read from the
|
|
92
|
+
environment, then the project `.env` next to `kaloko.config.yml`, then
|
|
93
|
+
`~/.config/kaloko/.env` (existing variables win), and are redacted from
|
|
94
|
+
captured HTML, page text and console output.
|
|
95
|
+
|
|
96
|
+
- **Protected environments** (staging, review apps): `access` sends HTTP Basic
|
|
97
|
+
credentials, service-token headers (Cloudflare Access, Vercel protection
|
|
98
|
+
bypass, your own) or a client certificate, to the environment's own origins
|
|
99
|
+
only. `base_url` may use `${VAR}` for review-app URLs from CI.
|
|
100
|
+
- **Signed-in users**: `accounts` maps the scenario sessions' `account` keys to
|
|
101
|
+
credentials per environment (user, password, TOTP). For SSO or MFA a person
|
|
102
|
+
signs in once with `npx kaloko auth save --env <env> --account <key>`.
|
|
103
|
+
- **E-mails**: built-in Mailpit client; any other mailbox through a small
|
|
104
|
+
adapter module (`provider: script`, example in `templates/mail/`), or hand a
|
|
105
|
+
message over with `npx kaloko mail --step <id> --file message.eml`.
|
|
106
|
+
- **Service and evaluator**: `KALOKO_TOKEN` for `share`, `feedback`, `inbox` and clean-up (`runs`, `trash`, `prune`, `keep`, `archive`)
|
|
107
|
+
(create it in your organization's settings); `TYPESAFE_API_KEY` for the
|
|
108
|
+
semantic evaluator (optional). Both names can be changed in the config.
|
|
109
|
+
|
|
110
|
+
`npx kaloko doctor` checks that every variable the config names is set and that
|
|
111
|
+
each environment lets you in.
|
|
112
|
+
|
|
113
|
+
Set `browser.channel: chrome` to use an installed Chrome, or run
|
|
114
|
+
`npx playwright install chromium`.
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
Proprietary. Use of Kaloko is subject to the terms at
|
|
119
|
+
<https://kaloko.app/terms>.
|
package/bin/kaloko.mjs
ADDED
package/bin/qawalk.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kaloko",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "See what your AI agents built: every screen, language and device walked, assessed and approved on one canvas.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"qa",
|
|
7
|
+
"acceptance-testing",
|
|
8
|
+
"playwright",
|
|
9
|
+
"claude-code",
|
|
10
|
+
"codex",
|
|
11
|
+
"agent-skills"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://kaloko.app",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"license": "UNLICENSED",
|
|
16
|
+
"bin": {
|
|
17
|
+
"kaloko": "bin/kaloko.mjs",
|
|
18
|
+
"qawalk": "bin/qawalk.mjs"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"bin",
|
|
22
|
+
"src",
|
|
23
|
+
"schemas",
|
|
24
|
+
"templates",
|
|
25
|
+
"viewer",
|
|
26
|
+
"skills/kaloko"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=20"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"test": "node --test --test-timeout=300000 test/*.test.mjs worker/test/*.test.mjs"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"ajv": "^8.20.0",
|
|
39
|
+
"js-yaml": "^4.1.0",
|
|
40
|
+
"playwright": "^1.55.0"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://qawalk.com/schemas/bundle.v1.json",
|
|
4
|
+
"title": "qawalk.bundle.v1",
|
|
5
|
+
"description": "The live files of one design step as the CLI and the service exchange them (#42). Paths are relative to the design folder: <step>/index.html (or <step>/<locale>/index.html), shared files in _shared/, the token set in tokens.json. Enforced by src/lib/design-core.mjs on both sides: at most 400 files, 10 MB per file, 40 MB per revision, 8 folders deep, 240 characters per path.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["entry", "files"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"entry": { "type": "string", "pattern": "\\.html$", "description": "The page of the step." },
|
|
11
|
+
"files": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"description": "Path → sha256 of the file content.",
|
|
14
|
+
"propertyNames": { "pattern": "^(?!/)(?!.*(?:^|/)\\.)[A-Za-z0-9_][A-Za-z0-9._-]*(?:/[A-Za-z0-9_][A-Za-z0-9._-]*)*\\.(html|css|js|mjs|json|svg|woff2|woff|png|jpg|jpeg|webp|avif|gif|mp4|webm|txt)$" },
|
|
15
|
+
"additionalProperties": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
|
|
16
|
+
"maxProperties": 400
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://qawalk.com/schemas/config.v1.json",
|
|
4
|
+
"title": "Kaloko project configuration (kaloko.config.yml)",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["schema", "org", "environments"],
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"schema": { "const": "qawalk.config.v1" },
|
|
10
|
+
"org": { "type": "string", "description": "Organization slug on kaloko.app." },
|
|
11
|
+
"project": { "type": "string" },
|
|
12
|
+
"scenarios": { "type": "array", "items": { "type": "string" }, "description": "Glob patterns of scenario files." },
|
|
13
|
+
"output": { "type": "string", "description": "Run folder; default tmp/kaloko (tmp/qawalk when only that one exists)" },
|
|
14
|
+
"browser": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"properties": {
|
|
18
|
+
"channel": { "type": "string", "description": "Playwright channel, e.g. chrome. Empty = bundled Chromium." },
|
|
19
|
+
"port": { "type": "integer", "default": 9333 }
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"environments": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"minProperties": 1,
|
|
25
|
+
"additionalProperties": { "$ref": "#/$defs/environment" }
|
|
26
|
+
},
|
|
27
|
+
"evaluators": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"additionalProperties": false,
|
|
30
|
+
"properties": {
|
|
31
|
+
"jev": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"additionalProperties": false,
|
|
34
|
+
"properties": {
|
|
35
|
+
"model": { "type": "string", "default": "jev-1.13.0" },
|
|
36
|
+
"api_key_env": { "type": "string", "default": "TYPESAFE_API_KEY" },
|
|
37
|
+
"base_url": { "type": "string", "default": "https://api.typesafe.ai" },
|
|
38
|
+
"thresholds": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"additionalProperties": false,
|
|
41
|
+
"properties": { "pass": { "type": "number" }, "fail": { "type": "number" } }
|
|
42
|
+
},
|
|
43
|
+
"max_state_chars": { "type": "integer", "default": 90000 },
|
|
44
|
+
"hosted": { "type": "boolean", "default": true, "description": "Without a local evaluator key, evaluate through the organization's service (plan allowance per month). false: only your own key." },
|
|
45
|
+
"signals": { "type": "boolean", "default": true, "description": "Quick signals on every screen (purpose met, expected language, looks broken); never change verdicts." },
|
|
46
|
+
"concurrency": { "type": "integer", "minimum": 1, "maximum": 16, "default": 6, "description": "Evaluator requests in flight at once." }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"share": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"additionalProperties": false,
|
|
54
|
+
"properties": {
|
|
55
|
+
"url": { "type": "string", "default": "https://kaloko.app" },
|
|
56
|
+
"token_env": { "type": "string", "default": "KALOKO_TOKEN" },
|
|
57
|
+
"expires_days": { "type": "integer", "default": 30 }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"$defs": {
|
|
62
|
+
"environment": {
|
|
63
|
+
"type": "object",
|
|
64
|
+
"additionalProperties": false,
|
|
65
|
+
"if": { "properties": { "kind": { "const": "design" } }, "required": ["kind"] },
|
|
66
|
+
"then": { "required": ["serve"] },
|
|
67
|
+
"else": { "anyOf": [{ "required": ["base_url"] }, { "required": ["app"] }] },
|
|
68
|
+
"properties": {
|
|
69
|
+
"kind": { "enum": ["app", "design"], "default": "app", "description": "app: the application under test (a web app at base_url, or a native app in the app block). design: a folder of live HTML steps served locally by the CLI (serve); its runs are published as design versions (#42)." },
|
|
70
|
+
"serve": { "type": "string", "description": "kind: design. Folder with one sub-folder per step (<step>/index.html, optional <step>/<locale>/index.html) and shared files in _shared/; relative to the config." },
|
|
71
|
+
"fixtures": { "type": "string", "description": "kind: design. Folder of JSON fixtures live steps may fetch instead of real APIs; relative to the config." },
|
|
72
|
+
"tokens_mode": { "type": "string", "description": "kind: design. Token mode (e.g. light, dark) steps are rendered in; default: the token set's first mode." },
|
|
73
|
+
"html_view": { "type": "boolean", "default": false, "description": "Experimental (#42): keep a static HTML view of every capture (assets rehosted, scripts removed, secrets scrubbed). Refused on production unless the environment is readonly." },
|
|
74
|
+
"base_url": {
|
|
75
|
+
"oneOf": [
|
|
76
|
+
{ "type": "string" },
|
|
77
|
+
{ "type": "object", "additionalProperties": { "type": "string" }, "description": "Per-locale base URL; key 'default' is the fallback." }
|
|
78
|
+
],
|
|
79
|
+
"description": "Base URL, or per-locale base URLs (key \"default\" is the fallback). ${VAR} is replaced from the environment, e.g. https://${REVIEW_HOST} for review apps."
|
|
80
|
+
},
|
|
81
|
+
"readonly": { "type": "boolean", "default": false },
|
|
82
|
+
"app": {
|
|
83
|
+
"type": "object",
|
|
84
|
+
"additionalProperties": false,
|
|
85
|
+
"description": "The app under test in this environment, per platform (scenario platform: android, ios, electron, desktop). Paths of app scenarios are deep links.",
|
|
86
|
+
"properties": {
|
|
87
|
+
"android": {
|
|
88
|
+
"type": "object", "additionalProperties": false,
|
|
89
|
+
"properties": {
|
|
90
|
+
"package": { "type": "string", "description": "Application id, e.g. com.acme.shop.staging." },
|
|
91
|
+
"activity": { "type": "string", "description": "Launch activity (default: the launcher activity)." },
|
|
92
|
+
"apk": { "type": "string", "description": "APK to install before the walk (path relative to the repository)." },
|
|
93
|
+
"install": { "type": "boolean" },
|
|
94
|
+
"serial": { "type": "string", "description": "adb device serial; default ANDROID_SERIAL or the only device." },
|
|
95
|
+
"device": { "type": "string", "description": "Label for the canvas; default the device model." },
|
|
96
|
+
"reset": { "type": "boolean", "description": "Clear app data at the start of every locale (a new user)." },
|
|
97
|
+
"adb": { "type": "string" }, "launch_wait": { "type": "integer" }, "settle": { "type": "integer" }
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"ios": {
|
|
101
|
+
"type": "object", "additionalProperties": false,
|
|
102
|
+
"properties": {
|
|
103
|
+
"bundle": { "type": "string", "description": "Bundle id, e.g. com.acme.shop." },
|
|
104
|
+
"app": { "type": "string", "description": ".app build for the simulator to install before the walk." },
|
|
105
|
+
"install": { "type": "boolean" },
|
|
106
|
+
"device": { "type": "string", "description": "Simulator name, e.g. iPhone 17; booted when needed." },
|
|
107
|
+
"udid": { "type": "string" },
|
|
108
|
+
"reset": { "type": "boolean" }, "args": { "type": "array", "items": { "type": "string" } },
|
|
109
|
+
"idb": { "type": "boolean", "description": "Use idb for the UI tree and taps when installed (default true)." },
|
|
110
|
+
"ocr": { "type": "boolean", "description": "Without idb, read the screen text by OCR (macOS Vision; default true)." },
|
|
111
|
+
"status_bar": { "type": "boolean", "description": "Clean status bar (9:41, full battery) for captures; default true." },
|
|
112
|
+
"scale": { "type": "integer" }, "launch_wait": { "type": "integer" }, "settle": { "type": "integer" }
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"electron": {
|
|
116
|
+
"type": "object", "additionalProperties": false,
|
|
117
|
+
"properties": {
|
|
118
|
+
"main": { "type": "string", "description": "Main script of the app (e.g. dist/main.js), started with the project's electron." },
|
|
119
|
+
"executable": { "type": "string", "description": "Electron binary or the packaged app's executable." },
|
|
120
|
+
"args": { "type": "array", "items": { "type": "string" } },
|
|
121
|
+
"env": { "type": "object", "additionalProperties": { "type": "string" } },
|
|
122
|
+
"size": { "type": "array", "items": { "type": "integer" }, "minItems": 2, "maxItems": 2 }
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"desktop": {
|
|
126
|
+
"type": "object", "additionalProperties": false,
|
|
127
|
+
"properties": {
|
|
128
|
+
"name": { "type": "string", "description": "The app as macOS shows it (window owner), e.g. Notes." },
|
|
129
|
+
"bundle": { "type": "string" }, "path": { "type": "string" },
|
|
130
|
+
"args": { "type": "array", "items": { "type": "string" } },
|
|
131
|
+
"launch": { "type": "boolean", "description": "Open the app at the start (default true)." },
|
|
132
|
+
"reset": { "type": "boolean" }, "ocr": { "type": "boolean" }, "launch_wait": { "type": "integer" }, "settle": { "type": "integer" }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"may_create_data": { "type": "boolean", "default": true },
|
|
138
|
+
"blocked_paths": { "type": "array", "items": { "type": "string" }, "description": "Path globs a readonly run must never open." },
|
|
139
|
+
"allowed_post_paths": { "type": "array", "items": { "type": "string" }, "description": "Path globs a readonly run may POST to (e.g. cart)." },
|
|
140
|
+
"http_auth": { "$ref": "#/$defs/basicAuth", "description": "Deprecated: use access.basic. Still read as access.basic." },
|
|
141
|
+
"mail": {
|
|
142
|
+
"type": "object",
|
|
143
|
+
"additionalProperties": false,
|
|
144
|
+
"properties": {
|
|
145
|
+
"provider": {
|
|
146
|
+
"enum": ["mailpit", "script", "none"],
|
|
147
|
+
"description": "mailpit: built-in REST client; script: a project adapter module (any other mailbox); none: capture e-mails with kaloko mail --file."
|
|
148
|
+
},
|
|
149
|
+
"url": { "type": "string" },
|
|
150
|
+
"user_env": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "description": "Deprecated: use auth.basic." },
|
|
151
|
+
"password_env": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "description": "Deprecated: use auth.basic." },
|
|
152
|
+
"address": { "type": "string", "description": "Recipient template, {run} is replaced by a short run id, e.g. qa+{run}@example.com." },
|
|
153
|
+
"script": {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"description": "provider: script — module path relative to the config; default export async ({ to, subject, since, options, root, env }) => message | null."
|
|
156
|
+
},
|
|
157
|
+
"options": { "type": "object", "description": "Free-form options handed to the script adapter." },
|
|
158
|
+
"auth": {
|
|
159
|
+
"type": "object",
|
|
160
|
+
"additionalProperties": false,
|
|
161
|
+
"properties": { "basic": { "$ref": "#/$defs/basicAuth" }, "headers": { "$ref": "#/$defs/headers" } }
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
"access": {
|
|
166
|
+
"type": "object",
|
|
167
|
+
"additionalProperties": false,
|
|
168
|
+
"description": "Protection in front of the whole environment (staging, review apps). The CLI applies it to every browser context it creates, for the listed origins only.",
|
|
169
|
+
"properties": {
|
|
170
|
+
"origins": {
|
|
171
|
+
"type": "array",
|
|
172
|
+
"items": { "type": "string" },
|
|
173
|
+
"description": "Origins that receive the credentials; default: the base URL origins. https://*.example.com covers subdomains."
|
|
174
|
+
},
|
|
175
|
+
"basic": { "$ref": "#/$defs/basicAuth" },
|
|
176
|
+
"headers": {
|
|
177
|
+
"$ref": "#/$defs/headers",
|
|
178
|
+
"description": "Service-token headers, e.g. CF-Access-Client-Id / CF-Access-Client-Secret, x-vercel-protection-bypass."
|
|
179
|
+
},
|
|
180
|
+
"client_certificate": {
|
|
181
|
+
"type": "object",
|
|
182
|
+
"additionalProperties": false,
|
|
183
|
+
"description": "Mutual TLS. *_file is a path relative to the config; *_env holds a PEM or a path.",
|
|
184
|
+
"properties": {
|
|
185
|
+
"cert_file": { "type": "string" },
|
|
186
|
+
"key_file": { "type": "string" },
|
|
187
|
+
"cert_env": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
|
|
190
|
+
"description": "Name of an environment variable (the value is never written in the config)."
|
|
191
|
+
},
|
|
192
|
+
"key_env": {
|
|
193
|
+
"type": "string",
|
|
194
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
|
|
195
|
+
"description": "Name of an environment variable (the value is never written in the config)."
|
|
196
|
+
},
|
|
197
|
+
"passphrase_env": {
|
|
198
|
+
"type": "string",
|
|
199
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
|
|
200
|
+
"description": "Name of an environment variable (the value is never written in the config)."
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
"accounts": {
|
|
207
|
+
"type": "object",
|
|
208
|
+
"description": "People who sign in to the application in this environment, keyed like the scenario sessions' `account`. Step scripts get them as session.credentials.",
|
|
209
|
+
"additionalProperties": {
|
|
210
|
+
"type": "object",
|
|
211
|
+
"additionalProperties": false,
|
|
212
|
+
"properties": {
|
|
213
|
+
"user": { "type": "string", "description": "Literal user name or e-mail (not secret)." },
|
|
214
|
+
"user_env": {
|
|
215
|
+
"type": "string",
|
|
216
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
|
|
217
|
+
"description": "Name of an environment variable (the value is never written in the config)."
|
|
218
|
+
},
|
|
219
|
+
"password_env": {
|
|
220
|
+
"type": "string",
|
|
221
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
|
|
222
|
+
"description": "Name of an environment variable (the value is never written in the config)."
|
|
223
|
+
},
|
|
224
|
+
"totp_env": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "description": "Base32 TOTP secret for MFA; scripts call session.credentials.totp()." },
|
|
225
|
+
"storage_state": { "type": "string", "description": "Saved sign-in (kaloko auth save); default <output>/.auth/<env>/<account>.json. Never commit it." }
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
"secretRef": {
|
|
232
|
+
"type": "object",
|
|
233
|
+
"additionalProperties": false,
|
|
234
|
+
"required": ["env"],
|
|
235
|
+
"properties": {
|
|
236
|
+
"env": {
|
|
237
|
+
"type": "string",
|
|
238
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
|
|
239
|
+
"description": "Name of an environment variable (the value is never written in the config)."
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"description": "A value read from the environment variable `env`."
|
|
243
|
+
},
|
|
244
|
+
"basicAuth": {
|
|
245
|
+
"type": "object",
|
|
246
|
+
"additionalProperties": false,
|
|
247
|
+
"required": ["user_env", "password_env"],
|
|
248
|
+
"properties": {
|
|
249
|
+
"user_env": {
|
|
250
|
+
"type": "string",
|
|
251
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
|
|
252
|
+
"description": "Name of an environment variable (the value is never written in the config)."
|
|
253
|
+
},
|
|
254
|
+
"password_env": {
|
|
255
|
+
"type": "string",
|
|
256
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
|
|
257
|
+
"description": "Name of an environment variable (the value is never written in the config)."
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
"description": "HTTP Basic credentials, both read from environment variables."
|
|
261
|
+
},
|
|
262
|
+
"headers": {
|
|
263
|
+
"type": "object",
|
|
264
|
+
"description": "Request headers; a string is a literal (non-secret) value, { env: NAME } reads a secret.",
|
|
265
|
+
"additionalProperties": { "oneOf": [{ "type": "string" }, { "$ref": "#/$defs/secretRef" }] }
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://qawalk.com/schemas/revision.v1.json",
|
|
4
|
+
"title": "qawalk.revision.v1",
|
|
5
|
+
"description": "A saved state of one step in one locale (and state) of a design draft (#42). The id is derived from the content (src/lib/design-core.mjs revisionId), so the same files make the same revision on every machine. Captures are renderings of a revision per viewport.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["id", "node", "locale", "entry", "files"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"id": { "type": "string", "pattern": "^[0-9a-f]{32}$" },
|
|
10
|
+
"node": { "type": "string" },
|
|
11
|
+
"locale": { "type": "string" },
|
|
12
|
+
"state": { "type": "string", "default": "default", "description": "default, a design state (empty, error, …) or view:<viewport> for an HTML view." },
|
|
13
|
+
"kind": { "enum": ["design", "html_view"], "default": "design" },
|
|
14
|
+
"entry": { "type": "string" },
|
|
15
|
+
"files": { "$ref": "bundle.v1.json#/properties/files" },
|
|
16
|
+
"tokens": { "type": ["object", "null"], "properties": { "project": { "type": ["string", "null"] }, "version": { "type": ["integer", "null"] }, "hash": { "type": ["string", "null"] } } },
|
|
17
|
+
"based_on": { "type": ["string", "null"], "description": "The revision this one changed (a canvas edit, a sync on top of the draft)." },
|
|
18
|
+
"captures": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"description": "Viewport → rendered capture: blobs of the screenshot, thumbnail and DOM snapshot, the probe record and the evaluation.",
|
|
21
|
+
"additionalProperties": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"required": ["image", "html", "record"],
|
|
24
|
+
"properties": {
|
|
25
|
+
"image": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
|
|
26
|
+
"thumb": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
|
|
27
|
+
"html": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
|
|
28
|
+
"record": { "type": "object" },
|
|
29
|
+
"evaluation": { "type": ["object", "null"] },
|
|
30
|
+
"renderer": { "type": "string" },
|
|
31
|
+
"mode": { "type": "string" }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|