@impeccable/reviews 0.1.8 → 0.1.10

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 CHANGED
@@ -24,7 +24,7 @@ Keys: Enter goes on, Esc cancels the intro or the sign-in and skips a question (
24
24
  | Flag | Default | What it does |
25
25
  | --- | --- | --- |
26
26
  | `--install-dir <path>` | the folder the command is run in | The folder to set up, a checkout of the repository or a folder inside one, so the command runs from anywhere: `npx @impeccable/reviews --install-dir ~/code/your-repo`. A relative path is taken from the folder the command is run in; `IMPECCABLE_REVIEWS_INSTALL_DIR` does the same when the option is absent. |
27
- | `--app <key>` | asked | On a repository with several apps, sets up that one app, by its key (such as `storefront`), without asking which. Without it, every run asks, with the apps that are on already picked. |
27
+ | `--app <key>` | asked | On a repository with several apps, sets up that one app, by its key (such as `storefront`): one confirm screen names it instead of the list of apps, and only that app is touched. Without it, every run asks, with the apps that are on already picked. |
28
28
  | `--host <origin>` | `https://impeccable.reviews` | Impeccable's address. Plain `http` only for localhost. |
29
29
  | `--model <id>` | the model the service hands out (Sonnet 5.5 today) | The model the setup agent runs on, through Impeccable's gateway. |
30
30
  | `--effort <level>` | `high` | `off`, `minimal`, `low`, `medium`, `high`, `xhigh` or `max`. |
@@ -88,7 +88,7 @@ A test account's password, typed hidden on the account's screen (after a screen
88
88
 
89
89
  What you type into any other question the agent asks, it reads. So a question whose title, prompt or hint names a token, a password, a secret, a key or a credential is typed hidden however the agent asked it, and the agent gets a reference, as for a test account's password. Every other question with a field says under it "Never enter a password, a token or a key here."
90
90
 
91
- Vercel's bypass secret, which lets reviews open previews behind Vercel's login, is handled the same way. The secret goes only to a preview the linked project serves: before anything is sent, the command reads the project this folder is linked to (`.vercel/project.json`, whose ids it takes only in Vercel's own form; once the run's own `vercel link` wrote that file, only what it wrote counts) through the Vercel CLI as you, and refuses, saying so, unless Vercel shows that project connected to this repository, with Deployment Protection in its settings, and the preview's deployment as the project's own (among its latest, or read on its own by its address), since a deployment GitHub lists can name any address and its page proves nothing about whose it is, or whether the login on it is Vercel's: a deployment can serve a page shaped like Vercel's login, and only your project's settings say whether Vercel's stands there. The same read decides which project the setup locks before its first deployment. When Vercel's login stands in front of a preview of that project, the command asks you once, on one screen that names the preview's address, whether to create a bypass secret for Impeccable, and on your yes creates it as you through the Vercel CLI, labelled "Impeccable reviews" (`vercel api` for Vercel's protection-bypass route; an older CLI's `vercel project protection enable --protection-bypass`), then reads it back from the project's settings. A project that already holds a secret with that label gives it without a question. When your role cannot read or make one, a screen names the settings page and the preview's address, and takes the secret you type, hidden; a folder that is not linked, or a CLI that is signed out, gets no such screen, since nothing then shows the preview to be yours. It opens the preview with the secret first and saves it, with the setting that sends it in the `x-vercel-protection-bypass` header, only once the page shows your app. The agent never holds it: the secret goes from the command's own process to Vercel and to Impeccable's setting, and the debug log and the transcript remove it. Vercel documents this as Protection Bypass for Automation, which every plan includes; you revoke it in the project's Settings, Deployment Protection.
91
+ Vercel's bypass secret, which lets reviews open previews behind Vercel's login, is handled the same way. The secret goes only to a preview the linked project serves: before anything is sent, the command reads the project this folder is linked to (`.vercel/project.json`, whose ids it takes only in Vercel's own form; once the run's own `vercel link` wrote that file, only what it wrote counts) through the Vercel CLI as you, and refuses, saying so, unless Vercel shows that project connected to this repository, with Deployment Protection in its settings, and the preview's deployment as the project's own (among its latest, or read on its own by its address), since a deployment GitHub lists can name any address and its page proves nothing about whose it is, or whether the login on it is Vercel's: a deployment can serve a page shaped like Vercel's login, and only your project's settings say whether Vercel's stands there. The same read decides which project the setup locks before its first deployment. When Vercel's login stands in front of a preview of that project, the command asks you once, on one screen that names the preview's address, whether to create a bypass secret for Impeccable, and on your yes creates it as you through the Vercel CLI, labelled "Impeccable reviews" (`vercel api` for Vercel's protection-bypass route; an older CLI's `vercel project protection enable --protection-bypass`), then reads it back from the project's settings and opens the preview with it, trying again for up to 30 seconds while Vercel's edge still answers with its login, since a secret made moments ago can take a few seconds to be honoured. A project that already holds a secret with that label gives it without a question. When that does not end with a secret that opens the preview, a screen says what stopped it in Vercel's own words (the CLI could not read the project; Vercel refused the make, which takes the Member role or Project Administrator; the secret was made but not read back, or did not open the preview, in which case the screen says to copy it rather than make another), opens that project's own Deployment Protection settings in your browser, under the team the project belongs to, names the preview's address, and takes the secret you type, hidden; a folder that is not linked, or a CLI that is signed out, gets no such screen, since nothing then shows the preview to be yours. It opens the preview with the secret first and saves it, with the setting that sends it in the `x-vercel-protection-bypass` header, only once the page shows your app. The agent never holds it: the secret goes from the command's own process to Vercel and to Impeccable's setting, and the debug log and the transcript remove it. Vercel documents this as Protection Bypass for Automation, which every plan includes; you revoke it in the project's Settings, Deployment Protection.
92
92
 
93
93
  Netlify's site password (Password Protection on Pro and Enterprise plans; "Project visibility: Password" on a credit-based Pro plan) is handled the same way. When a Netlify deploy preview asks for it, the command reads the site's settings through the Netlify CLI, signed in as you, and that read is what shows the site to be yours: a site the CLI cannot read as you (it is signed out, or the site is in none of your teams) gets no password, and the command refuses, saying so, since the lock at a listed address may be anyone's. For a password Netlify gives back, it asks you once, on one screen that names the preview's address, whether to store the site password for Impeccable, and on your yes reads it from the site as you. When Netlify does not give the password back, a screen names the address and takes the password you type, hidden (the run never sets one itself: the Netlify CLI takes a new password only on its command line, where any process could read it). It opens the preview with the password first, as basic credentials in the `Authorization` header (Netlify's password page asks for a password alone, so the credentials carry no username), and saves it, with the setting that sends that header, only once the page shows your app; a password that opens the preview on Netlify's own form but not in the header is reported, not saved, since reviews can send only a header. A site behind Netlify's team login (a private site) has no way in for tools, so the command asks you once, on one screen, whether to make the site public, and on your yes makes it public as you through the Netlify CLI (`netlify api updateSite` with `sso_login` off); anyone with its address can then open it, the live site included, until you make it private again in Project configuration, General, Visitor access. Where Netlify refuses (your team's default keeps every project private, or your role cannot change it), the command opens that page in your browser and asks you to try again once you changed it there; a password you set there instead is stored as above. The agent never holds the password: it goes from the command's own process to Netlify and to Impeccable's setting, and the debug log and the transcript remove it.
94
94
 
package/dist/bin.js CHANGED
File without changes
@@ -148,7 +148,7 @@ export const HOST_SCREENS = {
148
148
  kind: 'text',
149
149
  sensitive: true,
150
150
  title: 'Your Vercel previews are protected',
151
- prompt: 'Vercel keeps your previews behind a login, and the Vercel CLI here could not make a bypass secret for them: that takes the Member role, or Project Administrator. Make one yourself: your project → Settings → Deployment Protection → Protection Bypass for Automation → Create, named "Impeccable reviews". It is stored encrypted and used only to open previews.',
151
+ prompt: 'Vercel keeps your previews behind a login, and the run did not get a bypass secret in place for them. Make one yourself: your project → Settings → Deployment Protection → Protection Bypass for Automation → Create, named "Impeccable reviews". It is stored encrypted and used only to open previews.',
152
152
  hint: 'Paste the secret',
153
153
  },
154
154
  // Netlify's site password in front of the previews: the one consent to storing the password the run reads from the site as the person, and the paste when it cannot read it.
@@ -224,6 +224,20 @@ export function sentTo(screen, url) {
224
224
  const line = `This run sends it first to ${url}, to prove it opens before anything saves it.`;
225
225
  return screen.kind === 'confirm' ? { ...screen, hint: `${screen.hint} ${line}` } : { ...screen, prompt: `${screen.prompt} ${line}` };
226
226
  }
227
+ /**
228
+ * The paste screen for Vercel's bypass secret, saying what actually stopped the run's own way (the CLI's read, Vercel's
229
+ * refusal in its own words, a secret made but not read back, or one that did not open the preview) rather than one fixed
230
+ * cause: a project that holds a secret labelled for Impeccable already is one to copy from, not to make another on.
231
+ */
232
+ export function vercelBypassPaste(stopped) {
233
+ const where = 'your project → Settings → Deployment Protection → Protection Bypass for Automation';
234
+ const next = stopped.held === 'labelled'
235
+ ? `Copy the secret named "Impeccable reviews" from ${where} and paste it here, or create another one there with that name.`
236
+ : stopped.held === 'unlabelled'
237
+ ? `Copy the secret the run just made (the newest one there, with no note) from ${where} and paste it here, or create another one there, named "Impeccable reviews".`
238
+ : `Make one yourself: ${where} → Create, named "Impeccable reviews".`;
239
+ return { ...HOST_SCREENS['vercel-bypass-key'], prompt: `Vercel keeps your previews behind a login. ${stopped.reason} ${next} It is stored encrypted and used only to open previews.` };
240
+ }
227
241
  /** The apps question on a repository with several apps, worded here: the tool lists the apps the state has, each picked as it is on, so every run asks it the same way. */
228
242
  export const APPS_QUESTION = {
229
243
  id: 'apps',
@@ -234,6 +248,16 @@ export const APPS_QUESTION = {
234
248
  };
235
249
  /** The apps question's hint when the command was started below the repository's top: `where` is an app's folder ("Tally Board's folder") or the folder itself. */
236
250
  export const startedIn = (where) => `You started in ${where}. Impeccable sets up from the top of the repository.`;
251
+ /** The apps question when the command was started for one app (`--app`): no list, one confirm screen naming that app, and the list behind Skip for someone who wants another app (#286). */
252
+ export const namedAppQuestion = (app) => ({
253
+ id: APPS_QUESTION.id,
254
+ kind: 'confirm',
255
+ title: APPS_QUESTION.title,
256
+ hint: `You're setting up ${app.name} (${app.folder || '/'}); the other apps stay as they are.`,
257
+ prompt: `Set up ${app.name}?`,
258
+ confirmLabel: `Set up ${app.name}`,
259
+ skipLabel: 'Pick other apps',
260
+ });
237
261
  /** The ids whose screens the tool puts up itself, when it needs the person, and takes down: the web page follows those, not the model's call. */
238
262
  export const TOOL_SHOWN = new Set(['netlify-setup', 'vercel-setup', APPS_QUESTION.id]);
239
263
  /** A question as the person reads it: the fixed words for a host's id, else the model's own. */
package/dist/main.js CHANGED
@@ -16,7 +16,7 @@ import { scanRecorder } from './scan.js';
16
16
  import { createReporter, reportingOff } from './report.js';
17
17
  import { createSessionSync, pageStatus, plainReport, syncExtension } from './sync.js';
18
18
  import { checkPushAccess, readPushAccess } from './push-access.js';
19
- import { createTools, ownPullRequest, resultLine } from './tools.js';
19
+ import { appsSummary, createTools, ownPullRequest, resultLine } from './tools.js';
20
20
  import { transcriptPaths } from './transcript.js';
21
21
  import { askPerson } from './ui/bridge.js';
22
22
  import { atExit, closeScreens, helpMark, onScreenExit, recordFrames, showIntro, showOutro, showPullRequest, showRun, showSignIn } from './ui/screens.js';
@@ -235,14 +235,17 @@ export async function main(argv) {
235
235
  const saved = await settle(liveSync.flush(), 5000);
236
236
  const { testPr } = report;
237
237
  const setupPr = shownSetupPr(report.setupPr);
238
+ // On a repository with several apps, "You're all set up" means every app this run picked is: one left unproven is named, with its one step (#286).
239
+ const apps = appsSummary(report.apps ?? []);
240
+ const allSetUp = Boolean(testPr) && !apps.notReady.length;
238
241
  // One pull request a screen, each opened in the browser and put on the clipboard as its screen appears: the test drive, then the setup pull request.
239
242
  const hand = { open: openBrowser, copy: copyText };
240
243
  if (testPr && setupPr)
241
244
  await showPullRequest(testPr.url, hand);
242
245
  await showOutro({
243
- outcome: testPr ? 'done' : 'partial',
244
- title: testPr ? "You're all set up" : 'Settings saved',
245
- result: resultLine({ ...report, setupPr }),
246
+ outcome: allSetUp ? 'done' : 'partial',
247
+ title: allSetUp ? "You're all set up" : apps.notReady.length ? `${apps.notReady.join(' and ')} ${apps.notReady.length === 1 ? 'is' : 'are'} not set up` : 'Settings saved',
248
+ result: [resultLine({ ...report, setupPr }), apps.line].filter(Boolean).join(' '),
246
249
  link: (setupPr ?? testPr)?.url,
247
250
  links: [
248
251
  ...(testPr ? [{ label: 'Test drive, watch the review there', url: testPr.url }] : []),
@@ -250,7 +253,7 @@ export async function main(argv) {
250
253
  ...(setupPr ? [{ label: testPr ? 'Setup pull request, merge this' : 'Setup pull request', url: setupPr.url }] : []),
251
254
  { label: 'Web page', url: page },
252
255
  ],
253
- todo: report.left,
256
+ todo: [...apps.todo, ...report.left],
254
257
  warnings: [...removed, ...(saved && !saved.ok ? [`The web page missed the last update (${saved.error}), so it may lag behind this.`] : [])],
255
258
  }, hand);
256
259
  // The web page has the report; when it missed it, the report stays here instead.
@@ -5,14 +5,14 @@ The state's repository has an `apps` item: the scan proposed several apps, folde
5
5
  ### Steps
6
6
 
7
7
  1. **Confirm the proposal** as it stands, while the item's status is `needs-you`: impeccable_write to `apps` with the `confirm` action the item's instructions give. Its answer lists every app of the repository, on and off, with its `key`, `name`, `pathPrefixes` and `enabled`; the one the scan switched on is the repository's default. An item that is `done` or `skipped` was answered before (on the setup page, or by an earlier run): no confirm, and step 2 all the same. Done when it answered `apps`, or the item was answered before.
8
- 2. **Ask which apps this run sets up**, on every run, with impeccable_ask: `id: "apps"`, `kind: "multi"`, and the `prompt` *"Which apps should get Impeccable previews?"*. The tool words the question and lists the state's apps (the repository's own, `main`, only where the Worker kept it as a product of its own), each picked as it is on, or every one after this run's confirm. Mark the Apps task in progress first. Every write and host tool for an app is refused until it is answered. Done when it answered `values`, `named` (the command was started for that one app with `--app`, so no screen showed), or a skip, whose `on` lists the apps that are on: the ones this run sets up.
8
+ 2. **Ask which apps this run sets up**, on every run, with impeccable_ask: `id: "apps"`, `kind: "multi"`, and the `prompt` *"Which apps should get Impeccable previews?"*. The tool words the question and lists the state's apps (the repository's own, `main`, only where the Worker kept it as a product of its own), each picked as it is on, or every one after this run's confirm. Mark the Apps task in progress first. Every write and host tool for an app is refused until it is answered. Done when it answered `values`, `named` (the command was started for that one app with `--app`, from its card on the dashboard: the tool showed one confirm screen naming that app instead of the list, and the list all the same when the person asked for other apps there), or a skip, whose `on` lists the apps that are on: the ones this run sets up. After `named`, that app is the one this run sets up: every host read, key, proof, method and check is its own, and no other app is mentioned past that screen.
9
9
  3. **Write the picks**, one action a call as the item's instructions give them: `enable` each chosen app that is off, then `disable` each app that is on and was not chosen. The last app that is on cannot be switched off (409), which is why the enables come first. **After `named`**, `enable` that app when it is off, and switch no other off. **After Skip**, write nothing more: the apps that are on stay on. Done when the last answer's `apps` show `enabled` true for every chosen app and false for the rest (after `named`, true for that app), or, after Skip, nothing was written.
10
10
  4. **Read the state again** with impeccable_state. Done when the preview item's `apps` names each chosen app's `directory`, `build` and `method` (none yet for an app not set up), and `perApp` its status.
11
- 5. **Set each chosen app up**, one after the other, as the playbook's steps 3 and 4 say for that app alone, `appKey` on every write and check (`preview`, `test-accounts`, `latest-pull-check`, `connection-check`): its method by the case that applies to it (server-previews when its pages need a server, static-site when they do not, a host's case when the host deploys that app as a project of its own, proven on that app's own address: impeccable_hosted_previews, impeccable_netlify_previews and impeccable_cloudflare_previews take its `appKey` and list only the previews of the project or site that builds its folder, so another app's address, project or key never stands in for it; their `unmatched` says why none can be told, and that app goes as server-previews or static-site says, with the reason under "What is not verified"), and its own sign-in when the scan item's `accessByApp` says it has one, each account question's title naming the app (*"Order desk admin account"*). Done when every chosen app's method is saved, or its preview skipped as server-previews says, and its sign-in saved or skipped, and no other app got a write, a build or a question.
12
- 6. **The pull requests** as pull-requests says, once for the repository: the setup commit takes the state's one workflow `file` (a job for each chosen static site whose preview Impeccable builds) once every chosen app's method and build settings are saved, or its preview skipped as server-previews says; the test drive adds its page to every chosen app with a preview (an app whose preview was skipped gets none, and goes under "What was skipped, and why"), in that app's own framework and linked from that app's own public page, so one review renders each of them on its own preview; that case's step 3 proves each chosen app with the input that proved it; its step 6 checks once, with the `appKey` of the first chosen app with a preview, and the other apps' previews go under "What is not verified". Done when pull-requests' steps are done.
11
+ 5. **Set each chosen app up**, one after the other, as the playbook's steps 3 and 4 say for that app alone, `appKey` on every write and check (`preview`, `test-accounts`, `latest-pull-check`, `connection-check`): its method by the case that applies to it (server-previews when its pages need a server, static-site when they do not, a host's case when the host deploys that app as a project of its own, proven on that app's own address: impeccable_hosted_previews, impeccable_netlify_previews and impeccable_cloudflare_previews take its `appKey` and list only the previews of the project or site that builds its folder, so another app's address, project or key never stands in for it; their `unmatched` says why none can be told, and that app goes as server-previews or static-site says, with the reason under "What is not verified"), and its own sign-in when the scan item's `accessByApp` says it has one, each account question's title naming the app (*"Order desk admin account"*). **The lock in front of each app's previews is that app's own**: when its proof answers a `gate`, preview-protection's steps run for that app, with its `appKey`, before any other app's step (the tools refuse the next app's reads and writes until its key tool was called), and the key goes to that app's own project or site; a key saved for one app says nothing about another's, and the state's `keySaved` speaks for one app at most. Done when every chosen app's method is saved, or its preview skipped as server-previews says, and its sign-in saved or skipped, and no other app got a write, a build or a question.
12
+ 6. **The pull requests** as pull-requests says, once for the repository: the setup commit takes the state's one workflow `file` (a job for each chosen static site whose preview Impeccable builds) once every chosen app's method and build settings are saved, or its preview skipped as server-previews says; the test drive adds its page to every chosen app with a preview (an app whose preview was skipped gets none, and goes under "What was skipped, and why"), in that app's own framework and linked from that app's own public page, so one review renders each of them on its own preview; that case's step 3 proves each chosen app with the input that proved it; its step 4 proves the test drive's page on each chosen app's own preview, with that app's key where its lock stands in front; its step 6 checks each chosen app with a preview, with its `appKey`, one call each. Done when pull-requests' steps are done.
13
13
  - **A chosen app whose preview was skipped** (server-previews): it stays on, with no method, no job in the workflow and no test drive page. It holds nothing back: the other apps' setup commit, test drive and checks go on as above, and its checkup entry left in `next` counts as done for the playbook's step 5. The report says, on its line and under "What was skipped, and why", that it gets no preview until its host deploys them.
14
14
  - **A host previews some chosen apps and Impeccable builds the others**: a host's case speaks for its own app. The setup commit carries the workflow for the others and the test drive branches from it, and pull-requests' step 4 goes each app's way: the host's app proven on the host's build, the others by the workflow. The repository goes without a workflow and a setup pull request only where a host previews every chosen app.
15
- 7. **Report per app**: under "What was configured, and by whom", one line per app the question offered: on or off and why (picked, unticked, named with `--app`, on already after a skip), its method, its sign-in, what was verified; an app left out is under "What was skipped, and why" as well, with the setup page as where it is turned on. Done when every app is on one line.
15
+ 7. **Report per app**: under "What was configured, and by whom", one line per app the question offered: on or off and why (picked, unticked, named with `--app`, on already after a skip), its method, its sign-in, what was verified; an app left out is under "What was skipped, and why" as well, with the setup page as where it is turned on. impeccable_report adds a section of its own, "Each app, as this run left it", from what the run saved and proved, and the last screen says "You're all set up" only when every chosen app is: an app whose preview met a lock with no key saved, or got no method, is named there with its one step, so the report's lines say the same. Done when every app is on one line.
16
16
 
17
17
  ### Reference
18
18
 
@@ -20,7 +20,7 @@ impeccable_prove_preview answered a `gate`: the host's own lock stands in front
20
20
 
21
21
  - **The report** names, under "What was configured, and by whom", the Vercel project that holds the secret named "Impeccable reviews" (`project`), whether this run created it, found it there or the person typed it, and where it is revoked: the project's Settings → Deployment Protection → Protection Bypass for Automation; or the Netlify site (`site`) whose password is stored, whether this run read it from the site or the person typed it, and where it is changed: the site's Project configuration → General → Visitor access; or, with `opened`, the Netlify site made public, by this run on the person's yes or by the person on Netlify's page (`madePublic`), so anyone with its address opens it, and where it is made private again: the same Visitor access; or the service token named "Impeccable reviews", whether this run created it or the person typed it, the Access application whose policy allows it (`application`), when a created one runs out (`expires`), and where it is revoked: Zero Trust → Access controls → Service credentials → Service Tokens; with `apiToken`, the Cloudflare API token the person made for the run is theirs to delete (dash.cloudflare.com/profile/api-tokens). Revoking, regenerating or changing it stops reviews until a new one is saved on the setup page.
22
22
  - **The tool does the writes**: the key as Impeccable's credential for the lock, and the setting that sends it in the host's header (`x-vercel-protection-bypass`, `Authorization`, or `CF-Access-Client-Id` and `CF-Access-Client-Secret`), both through the setup API, so impeccable_write refuses those two. The state's `preview-protection` item words the same calls, and shows `keySaved` once they are done.
23
- - **A key saved before** (the item shows `keySaved` and a `check` that `passed`): the lock was handled by an earlier run or the person. Run step 2's check and go on; call the tool only when that check fails.
23
+ - **A key saved before** (the item shows `keySaved` and a `check` that `passed`): the lock was handled by an earlier run or the person. Run step 2's check and go on; call the tool only when that check fails. On a repository with several apps, the item's `keySaved` speaks for one app at most: an app whose own proof answered a `gate` gets step 1 with its `appKey`, whatever another app's key did, and its step 2 check is its own.
24
24
  - **The key is never yours**: it goes from the command's own process to the host and to Impeccable, and into no message, status line, file, command or report. `vercel project protection`, `vercel api`, `vercel curl` and `netlify api` print it, and the fence refuses them.
25
25
  - **The app's own sign-in** is another card: a preview opened past the lock proves nothing about it.
26
26
  - **Status lines** belong to the Preview method task. Word Vercel's login and Cloudflare Access as a login, and Netlify's lock as a password.
@@ -2,6 +2,8 @@
2
2
 
3
3
  Vercel deploys previews of the pull requests: impeccable_hosted_previews lists a successful Preview deployment that Vercel made (`vercel: true`) of a pull request, with its address. The checkout often shows it too (`vercel.json`, `.vercel/project.json`, a `vercel` dependency), but GitHub's record decides. Vercel builds and serves every preview, so these steps replace the playbook's step 3, and the repository needs no workflow and no setup pull request.
4
4
 
5
+ It applies as well **before the first pull request**: Vercel deploys the repository already (impeccable_hosted_previews lists deployments Vercel made, production ones or of pushes, and none of a pull request; on a repository with several apps, those of the project that builds the app, named in `project`), so its previews start with the test drive's push. Then there is nothing to prove in step 1 yet: impeccable_ask with `vercel-setup` is refused, since there is no sign-in, project or connection to make; go on to pull-requests' step 4, which pushes the test drive, waits for Vercel's deployment of the pushed branch (impeccable_hosted_previews with `branch`, and the app's `appKey`), proves the test drive's page there, past Vercel's login as preview-protection says, and then step 2 saves the method.
6
+
5
7
  ### Steps
6
8
 
7
9
  1. **Prove the newest preview** with impeccable_prove_preview: the address of the newest successful Preview deployment of a pull request (on a repository with several apps, the newest of those impeccable_hosted_previews listed for the app's `appKey`, the deployments of the Vercel project that builds its folder) (or a page on it a visitor opens without signing in, when the app's own sign-in answers there), and words the page shows that the checkout holds, such as the app's name in its title. Done when it answers `proven: true`; when an address no longer answers, try the next newest, three at most.
@@ -1,6 +1,6 @@
1
1
  ### When this applies
2
2
 
3
- The checkout is set up for Vercel (`vercel.json`, `.vercel/project.json`, a `vercel` dependency or script), or the person picked Vercel in server-previews, and Vercel has never deployed it: impeccable_hosted_previews lists no deployment that Vercel made (`vercel: true`), and no `error` (an error says nothing either way). These steps replace the playbook's step 3. As in vercel-previews, the repository needs no workflow and no setup pull request.
3
+ The checkout is set up for Vercel (`vercel.json`, `.vercel/project.json`, a `vercel` dependency or script), or the person picked Vercel in server-previews, and Vercel has never deployed it: impeccable_hosted_previews lists no deployment that Vercel made (`vercel: true`) of any kind, production ones included, and no `error` (an error says nothing either way); on a repository with several apps, it names no project of the app's (`unmatched`). A repository Vercel deploys already, with no pull request yet, is vercel-previews' ("before the first pull request"), and step 1's screen is refused for it. These steps replace the playbook's step 3. As in vercel-previews, the repository needs no workflow and no setup pull request.
4
4
 
5
5
  ### Steps
6
6