@tryvitris/website-harness 0.1.0-beta.7 → 1.0.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.
Files changed (75) hide show
  1. package/README.md +49 -117
  2. package/agent/graph.yaml +12 -6
  3. package/agent/refs/admin.md +11 -0
  4. package/agent/refs/analytics.md +17 -0
  5. package/agent/refs/launch.md +15 -11
  6. package/agent/refs/performance.md +1 -1
  7. package/bin/api/agent/evaluate.js +5 -5
  8. package/bin/api/agent/grade.js +5 -5
  9. package/bin/api/cli/api.js +15 -13
  10. package/bin/api/cli.js +15 -15
  11. package/bin/api/engine.js +6 -6
  12. package/bin/api/hosting.js +9 -7
  13. package/bin/api/index.js +2 -2
  14. package/bin/api/render.js +1 -1
  15. package/bin/chunks/{chunk-ZIROO2U4.js → chunk-37F7XIMH.js} +4 -3
  16. package/bin/chunks/{chunk-TTAUU3AZ.js → chunk-3OKR5AZJ.js} +1 -1
  17. package/bin/chunks/{chunk-PGFFKPK6.js → chunk-A2XMAPVW.js} +2 -2
  18. package/bin/chunks/{chunk-O55LAQ2C.js → chunk-FGSQE3DU.js} +2 -2
  19. package/bin/chunks/{chunk-VTI32UGJ.js → chunk-H3BS2EBR.js} +2 -2
  20. package/bin/chunks/{chunk-DSS2U2OM.js → chunk-KVMZSQ3D.js} +8 -2
  21. package/bin/chunks/{chunk-4MFPATAB.js → chunk-L44ZTNDM.js} +12 -5
  22. package/bin/chunks/{chunk-7V3OKLKH.js → chunk-LZC37OJZ.js} +4 -4
  23. package/bin/chunks/{chunk-5YSPWKFF.js → chunk-PYCRUMCT.js} +1 -1
  24. package/bin/chunks/{chunk-QRWGFLUU.js → chunk-R2WRQDVE.js} +2 -2
  25. package/bin/chunks/{chunk-YZWEXHT4.js → chunk-SEMH6MCV.js} +129 -21
  26. package/bin/chunks/{chunk-H7Y72HXC.js → chunk-UFTVWTEZ.js} +26 -7
  27. package/bin/chunks/{chunk-P56ZDMX7.js → chunk-WMJVLMU2.js} +16 -4
  28. package/bin/chunks/{chunk-FRABKM65.js → chunk-XY73ZLHB.js} +12 -9
  29. package/bin/chunks/{chunk-ZWFG4GPG.js → chunk-YXJAQYDE.js} +69 -53
  30. package/bin/chunks/{design-context-store-DCZOAK56.js → design-context-store-W3VTZ4HA.js} +5 -5
  31. package/bin/chunks/{packets-QOLWPRNV.js → packets-LBMDIFPO.js} +5 -5
  32. package/bin/chunks/{preparation-T2IOD5SJ.js → preparation-AV4PDQY6.js} +5 -5
  33. package/bin/chunks/{template-gallery-ET76ERZQ.js → template-gallery-H2SVYNRD.js} +1 -1
  34. package/bin/cloudflare/backend.js +144 -62
  35. package/bin/types/src/admin/connection.d.ts +3 -0
  36. package/bin/types/src/cli/admin.d.ts +21 -0
  37. package/bin/types/src/cli/api.d.ts +1 -1
  38. package/bin/types/src/cli/deploy.d.ts +2 -0
  39. package/bin/types/src/cli/doctor.d.ts +1 -0
  40. package/bin/types/src/cli/site-create.d.ts +2 -0
  41. package/bin/types/src/compile/site.d.ts +1 -1
  42. package/bin/types/src/integrations/hosting.d.ts +2 -0
  43. package/bin/vitris-art.js +5 -5
  44. package/bin/vitris-build.js +3 -3
  45. package/bin/vitris-create-site.js +9 -7
  46. package/bin/vitris-cursor-hook.js +5 -5
  47. package/bin/vitris-eval.js +7 -7
  48. package/bin/vitris-go.js +7 -7
  49. package/bin/vitris-harvest.js +6 -6
  50. package/bin/vitris-knowledge.js +6 -6
  51. package/bin/vitris-launch-preflight.js +5 -5
  52. package/bin/vitris-motion-view.js +5 -5
  53. package/bin/vitris-references.js +3 -3
  54. package/bin/vitris-refresh.js +6 -6
  55. package/bin/vitris-stock.js +1 -1
  56. package/bin/vitris-templates.js +1 -1
  57. package/bin/vitris-themes.js +5 -5
  58. package/bin/vitris-upgrade.js +6 -6
  59. package/bin/vitris-verify-browser.js +5 -5
  60. package/bin/vitris-verify-performance.js +3 -3
  61. package/bin/vitris.js +15 -15
  62. package/docs/ADMIN.md +85 -0
  63. package/docs/CLI.md +14 -6
  64. package/docs/CLOUDFLARE.md +27 -2
  65. package/docs/DISTRIBUTION.md +5 -3
  66. package/docs/ENGINE.md +6 -0
  67. package/docs/PRESERVE.md +1 -1
  68. package/docs/SECURITY.md +2 -2
  69. package/package.json +28 -23
  70. package/templates/site/AGENTS.md +4 -2
  71. package/templates/site/README.md +8 -3
  72. package/templates/site/deployment/README.md +24 -0
  73. package/templates/site/{.github/workflows/deploy.yml → deployment/github-actions.yml.example} +5 -6
  74. package/templates/site/gitignore +3 -0
  75. package/templates/site/package.json +3 -1
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  upgradeSite
4
- } from "./chunks/chunk-PGFFKPK6.js";
4
+ } from "./chunks/chunk-A2XMAPVW.js";
5
5
  import "./chunks/chunk-JCRGE6AL.js";
6
- import "./chunks/chunk-FRABKM65.js";
7
- import "./chunks/chunk-DSS2U2OM.js";
6
+ import "./chunks/chunk-XY73ZLHB.js";
7
+ import "./chunks/chunk-KVMZSQ3D.js";
8
8
  import "./chunks/chunk-WOORR67N.js";
9
9
  import "./chunks/chunk-PRLL7B63.js";
10
10
  import "./chunks/chunk-5JTBC6UK.js";
@@ -17,9 +17,9 @@ import "./chunks/chunk-AUO5I56E.js";
17
17
  import "./chunks/chunk-BIEDSEL2.js";
18
18
  import "./chunks/chunk-IKNMBGGD.js";
19
19
  import "./chunks/chunk-WEFDVXFX.js";
20
- import "./chunks/chunk-VTI32UGJ.js";
21
- import "./chunks/chunk-4MFPATAB.js";
22
- import "./chunks/chunk-ZIROO2U4.js";
20
+ import "./chunks/chunk-H3BS2EBR.js";
21
+ import "./chunks/chunk-L44ZTNDM.js";
22
+ import "./chunks/chunk-37F7XIMH.js";
23
23
  import "./chunks/chunk-LKN75JGA.js";
24
24
  import "./chunks/chunk-YYPYYOEV.js";
25
25
  import "./chunks/chunk-GZDLXYZV.js";
@@ -33,7 +33,7 @@ if (!command || command === "--help") {
33
33
  if (!site) throw new Error("--site required");
34
34
  const item = readStockCatalog(catalogPath).items.find((i) => i.id === id);
35
35
  if (!item) throw new Error("Unknown stock asset");
36
- const { findActivePreparation } = await import("./chunks/preparation-T2IOD5SJ.js");
36
+ const { findActivePreparation } = await import("./chunks/preparation-AV4PDQY6.js");
37
37
  const current = existsSync(join(site, "agent/PREPARED.json"));
38
38
  if (current && !findActivePreparation(site, "media") && !findActivePreparation(site, "asset-production")) throw new Error("Import stock during media or asset-production; route later additions through the declared owner");
39
39
  const launch = existsSync(join(site, "launch.json")) ? json(join(site, "launch.json")) : {};
@@ -100,7 +100,7 @@ async function verifyEntry(entry) {
100
100
  });
101
101
  }
102
102
  if (command === "gallery") {
103
- const { startTemplateGallery } = await import("./chunks/template-gallery-ET76ERZQ.js");
103
+ const { startTemplateGallery } = await import("./chunks/template-gallery-H2SVYNRD.js");
104
104
  const port = argv.includes("--port") ? Number(arg("--port")) : 4390;
105
105
  if (!Number.isInteger(port) || port < 0 || port > 65535) throw Error("Invalid gallery port");
106
106
  console.log("Default Cloudflare template gallery: " + (await startTemplateGallery(port)).url);
@@ -19,8 +19,8 @@ import {
19
19
  thumbnailService,
20
20
  validateAdaptationPreferences,
21
21
  writeThemePicker
22
- } from "./chunks/chunk-FRABKM65.js";
23
- import "./chunks/chunk-DSS2U2OM.js";
22
+ } from "./chunks/chunk-XY73ZLHB.js";
23
+ import "./chunks/chunk-KVMZSQ3D.js";
24
24
  import "./chunks/chunk-WOORR67N.js";
25
25
  import "./chunks/chunk-PRLL7B63.js";
26
26
  import "./chunks/chunk-5JTBC6UK.js";
@@ -45,9 +45,9 @@ import {
45
45
  import "./chunks/chunk-BIEDSEL2.js";
46
46
  import "./chunks/chunk-IKNMBGGD.js";
47
47
  import "./chunks/chunk-WEFDVXFX.js";
48
- import "./chunks/chunk-VTI32UGJ.js";
49
- import "./chunks/chunk-4MFPATAB.js";
50
- import "./chunks/chunk-ZIROO2U4.js";
48
+ import "./chunks/chunk-H3BS2EBR.js";
49
+ import "./chunks/chunk-L44ZTNDM.js";
50
+ import "./chunks/chunk-37F7XIMH.js";
51
51
  import "./chunks/chunk-LKN75JGA.js";
52
52
  import "./chunks/chunk-YYPYYOEV.js";
53
53
  import "./chunks/chunk-GZDLXYZV.js";
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  upgradeSite
4
- } from "./chunks/chunk-PGFFKPK6.js";
4
+ } from "./chunks/chunk-A2XMAPVW.js";
5
5
  import "./chunks/chunk-JCRGE6AL.js";
6
- import "./chunks/chunk-FRABKM65.js";
7
- import "./chunks/chunk-DSS2U2OM.js";
6
+ import "./chunks/chunk-XY73ZLHB.js";
7
+ import "./chunks/chunk-KVMZSQ3D.js";
8
8
  import "./chunks/chunk-WOORR67N.js";
9
9
  import "./chunks/chunk-PRLL7B63.js";
10
10
  import "./chunks/chunk-5JTBC6UK.js";
@@ -17,9 +17,9 @@ import "./chunks/chunk-AUO5I56E.js";
17
17
  import "./chunks/chunk-BIEDSEL2.js";
18
18
  import "./chunks/chunk-IKNMBGGD.js";
19
19
  import "./chunks/chunk-WEFDVXFX.js";
20
- import "./chunks/chunk-VTI32UGJ.js";
21
- import "./chunks/chunk-4MFPATAB.js";
22
- import "./chunks/chunk-ZIROO2U4.js";
20
+ import "./chunks/chunk-H3BS2EBR.js";
21
+ import "./chunks/chunk-L44ZTNDM.js";
22
+ import "./chunks/chunk-37F7XIMH.js";
23
23
  import "./chunks/chunk-LKN75JGA.js";
24
24
  import "./chunks/chunk-YYPYYOEV.js";
25
25
  import "./chunks/chunk-GZDLXYZV.js";
@@ -11,8 +11,8 @@ import {
11
11
  observeMotion,
12
12
  templateMotionHash,
13
13
  validateTemplateMotionPlan
14
- } from "./chunks/chunk-FRABKM65.js";
15
- import "./chunks/chunk-DSS2U2OM.js";
14
+ } from "./chunks/chunk-XY73ZLHB.js";
15
+ import "./chunks/chunk-KVMZSQ3D.js";
16
16
  import "./chunks/chunk-WOORR67N.js";
17
17
  import "./chunks/chunk-PRLL7B63.js";
18
18
  import "./chunks/chunk-5JTBC6UK.js";
@@ -37,9 +37,9 @@ import {
37
37
  } from "./chunks/chunk-WEFDVXFX.js";
38
38
  import {
39
39
  buildVerified
40
- } from "./chunks/chunk-VTI32UGJ.js";
41
- import "./chunks/chunk-4MFPATAB.js";
42
- import "./chunks/chunk-ZIROO2U4.js";
40
+ } from "./chunks/chunk-H3BS2EBR.js";
41
+ import "./chunks/chunk-L44ZTNDM.js";
42
+ import "./chunks/chunk-37F7XIMH.js";
43
43
  import "./chunks/chunk-LKN75JGA.js";
44
44
  import "./chunks/chunk-YYPYYOEV.js";
45
45
  import "./chunks/chunk-GZDLXYZV.js";
@@ -7,9 +7,9 @@ import {
7
7
  } from "./chunks/chunk-WEFDVXFX.js";
8
8
  import {
9
9
  buildVerified
10
- } from "./chunks/chunk-VTI32UGJ.js";
11
- import "./chunks/chunk-4MFPATAB.js";
12
- import "./chunks/chunk-ZIROO2U4.js";
10
+ } from "./chunks/chunk-H3BS2EBR.js";
11
+ import "./chunks/chunk-L44ZTNDM.js";
12
+ import "./chunks/chunk-37F7XIMH.js";
13
13
  import "./chunks/chunk-LKN75JGA.js";
14
14
  import "./chunks/chunk-YYPYYOEV.js";
15
15
  import "./chunks/chunk-GZDLXYZV.js";
package/bin/vitris.js CHANGED
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "./chunks/chunk-YZWEXHT4.js";
5
- import "./chunks/chunk-ZWFG4GPG.js";
6
- import "./chunks/chunk-O55LAQ2C.js";
7
- import "./chunks/chunk-P56ZDMX7.js";
8
- import "./chunks/chunk-PGFFKPK6.js";
9
- import "./chunks/chunk-H7Y72HXC.js";
4
+ } from "./chunks/chunk-SEMH6MCV.js";
5
+ import "./chunks/chunk-YXJAQYDE.js";
6
+ import "./chunks/chunk-FGSQE3DU.js";
7
+ import "./chunks/chunk-WMJVLMU2.js";
8
+ import "./chunks/chunk-A2XMAPVW.js";
9
+ import "./chunks/chunk-UFTVWTEZ.js";
10
10
  import "./chunks/chunk-2NW7KSPA.js";
11
- import "./chunks/chunk-TTAUU3AZ.js";
12
- import "./chunks/chunk-7V3OKLKH.js";
13
- import "./chunks/chunk-QRWGFLUU.js";
11
+ import "./chunks/chunk-3OKR5AZJ.js";
12
+ import "./chunks/chunk-LZC37OJZ.js";
13
+ import "./chunks/chunk-R2WRQDVE.js";
14
14
  import "./chunks/chunk-34H54KEY.js";
15
15
  import "./chunks/chunk-JCRGE6AL.js";
16
16
  import "./chunks/chunk-XL2DRAYI.js";
17
- import "./chunks/chunk-5YSPWKFF.js";
17
+ import "./chunks/chunk-PYCRUMCT.js";
18
18
  import "./chunks/chunk-XGTHGWPW.js";
19
- import "./chunks/chunk-FRABKM65.js";
20
- import "./chunks/chunk-DSS2U2OM.js";
19
+ import "./chunks/chunk-XY73ZLHB.js";
20
+ import "./chunks/chunk-KVMZSQ3D.js";
21
21
  import "./chunks/chunk-WOORR67N.js";
22
22
  import "./chunks/chunk-PRLL7B63.js";
23
23
  import "./chunks/chunk-5JTBC6UK.js";
@@ -30,9 +30,9 @@ import "./chunks/chunk-AUO5I56E.js";
30
30
  import "./chunks/chunk-BIEDSEL2.js";
31
31
  import "./chunks/chunk-IKNMBGGD.js";
32
32
  import "./chunks/chunk-WEFDVXFX.js";
33
- import "./chunks/chunk-VTI32UGJ.js";
34
- import "./chunks/chunk-4MFPATAB.js";
35
- import "./chunks/chunk-ZIROO2U4.js";
33
+ import "./chunks/chunk-H3BS2EBR.js";
34
+ import "./chunks/chunk-L44ZTNDM.js";
35
+ import "./chunks/chunk-37F7XIMH.js";
36
36
  import "./chunks/chunk-LKN75JGA.js";
37
37
  import "./chunks/chunk-YYPYYOEV.js";
38
38
  import "./chunks/chunk-GZDLXYZV.js";
package/docs/ADMIN.md ADDED
@@ -0,0 +1,85 @@
1
+ # Separate business admin
2
+
3
+ The business owns a separate installation, accounts, D1 database, R2 bucket and Worker at `admin.customer-domain.com`. No central Vitris login is required. Pages, Media, page builders and arbitrary HTML editing are outside scope. The public website keeps its forms, backend origin, tenant identity, consent behavior and release gates.
4
+
5
+ The harness pins `@tryvitris/website-admin-harness` and `@tryvitris/website-admin-contracts` to **0.1.0-alpha.1**. Setup delegates to the published runtime's `/cli` export (`vitris-admin`); its Worker uses `/worker`. The separate initializer is `@tryvitris/create-website-admin-harness@0.1.0-alpha.1`. Never use a floating `alpha` tag for a reproducible installation. See the [upstream source](https://github.com/jackperrotta/website-admin-harness).
6
+
7
+ ## Local preparation
8
+
9
+ New websites may opt into next-step instructions with `vitris site create ... --admin` or `vitris-create-site ... --admin`. This creates `ADMIN-SETUP.md` only. Continue prepare → `agent/CURRENT.md` → work → complete and stop at verified local preview as usual. Existing websites can run setup directly.
10
+
11
+ Inspect the site's launch configuration, forms, exact public origin, and actual backend tenant ID. A slug is not proof of tenant identity. Prepare the sibling admin with:
12
+
13
+ ```sh
14
+ vitris admin setup --site ../acme --dir ../acme-admin --domain admin.customer-domain.com --website https://www.customer-domain.com --tenant EXISTING_TENANT_ID --backend-origin https://BACKEND --plan
15
+ ```
16
+
17
+ Equivalent standalone published command:
18
+
19
+ ```sh
20
+ npx --yes @tryvitris/website-admin-harness@0.1.0-alpha.1 setup --site ../acme --dir ../acme-admin --domain admin.customer-domain.com --website https://www.customer-domain.com --tenant EXISTING_TENANT_ID --backend-origin https://BACKEND --plan
21
+ ```
22
+
23
+ Review `../acme/artifacts/admin/setup-plan.json`, including its exact directories, origins, tenant, scopes, package version and launch digest. Set a new dedicated `VITRIS_ADMIN_API_TOKEN` in the operator environment: 32–200 URL-safe letters/digits/underscores/hyphens generated by a secure secret manager. Repeat the identical command with `--apply` replacing `--plan`. Never pass the credential as a command argument or print it. `--lead-write` must appear in both commands only if lead status updates are explicitly wanted; default scopes are `leads:read` and `analytics:read`.
24
+
25
+ Apply brands the installation from `launch.json.name`, writes public `launch.json.admin` metadata, and saves only its SHA-256 hash in the admin's ignored `.vitris/backend-grant.json`. Existing forms, backend URL and workflow progress stay intact. Matching retries are no-ops; changed launch bytes/plans, conflicting destinations/connections or changed authority require a new review. Do not delete setup receipts or use force to bypass conflicts. Keep `artifacts/`, `.vitris/`, `.env*`, `.dev.vars*`, `dist/` and local release bundles ignored. No tenant, cloud resource, account, secret, DNS record or deployment is created by setup.
26
+
27
+ Inside the admin, install dependencies and retain its lockfile. Read `agent/WORKFLOW.md`, `agent/refs/harness.md`, and `agent/refs/cloudflare.md` before changing the installation. `npm run db:local` and `npm run dev` use a separate local manifest/database with synthetic demo data. They do not establish production backend access or working email authentication.
28
+
29
+ ## Backend compatibility and grants
30
+
31
+ This source adds the admin v1 API. **An already deployed website backend may still run an older revision.** Setup does not upgrade it. Identify its owner, deployed revision, schema and hostname; perform any backend release as a separately reviewed operation. Never deploy or migrate a shared backend as an admin setup side effect. No production endpoint or credential is included in this public repository, so an existing deployment's compatibility must be checked per installation.
32
+
33
+ `vitris admin status --site ../acme` reports local metadata only. After the grant is installed, use the dedicated credential in the operator environment to check the deployed API:
34
+
35
+ ```sh
36
+ vitris admin verify --site ../acme --dir ../acme-admin
37
+ ```
38
+
39
+ Verify requires v1 identity matching installation, tenant and site origin, both read scopes, and valid production leads, test submissions and analytics responses. It reports counts only; zero rows are valid. It fails on missing routes, rejected/revoked credentials, identity mismatch, malformed records, redirects or transport failure. It does not certify collection, email, account login or deployment. The admin's published adapter likewise surfaces failures without substituting demo records.
40
+
41
+ The backend secret `ADMIN_CONNECTIONS` is a COMPLETE installation-keyed map. Each grant contains only `tenantId`, exact HTTPS `siteOrigin`, `tokenHash` and `scopes`. Retrieve the authoritative full map from the backend owner's secure configuration; Wrangler cannot recover a secret's value. For a confirmed brand-new backend only, initialize a private ignored file with `{}`. Do not treat an unknown existing map as empty.
42
+
43
+ ```sh
44
+ vitris admin grant --dir ../acme-admin --grants PRIVATE_COMPLETE_MAP.json --out NEW_PRIVATE_MERGED_MAP.json
45
+ ```
46
+
47
+ This local command preserves other grants, validates hashed entries and installation identity, refuses differing existing authority and refuses overwriting the output. Store input/output in ignored operator storage. Review the entire merged map before explicitly uploading it to the intended backend as `ADMIN_CONNECTIONS` via Wrangler secret stdin. Rotation/revocation is a separate reviewed complete-map update: replace the hash or remove only that installation. Never reuse forms, deployment, personal Cloudflare or session credentials.
48
+
49
+ Upload the matching RAW credential to this admin as `HARNESS_API_TOKEN`, through secret stdin. For example, from the admin directory, with the dedicated token already in the operator environment (PowerShell and POSIX shells both support this pipeline):
50
+
51
+ ```sh
52
+ node -e "process.stdout.write(process.env.VITRIS_ADMIN_API_TOKEN || '')" | npx wrangler secret put HARNESS_API_TOKEN --config wrangler.jsonc
53
+ ```
54
+
55
+ Require a nonempty valid environment token before running this command. Install the reviewed complete backend map similarly, by piping the ignored file bytes to `wrangler secret put ADMIN_CONNECTIONS` with the backend's exact config/account. These are explicit cloud writes, outside local setup. Never log secret stdin or store raw tokens in files or public assets.
56
+
57
+ ## API and stored data
58
+
59
+ Server-to-server requests use `Authorization: Bearer ...`, `x-vitris-installation` and `x-vitris-site-origin`. The routes are `/api/admin/v1/TENANT/status`, `/leads`, `/leads?mode=test`, `/analytics?days=14`, and optional POST `/leads/status` with JSON `{id,status}`. Cookie login, browser Origin requests, forms setup tokens and deployment tokens grant no API access. All responses are uncached; preview hosts cannot reach these routes.
60
+
61
+ Every query constrains the existing tenant ID. Production reads use `leads`, including retained legacy records. Test reads use `form_submissions WHERE mode='test'` and matching notification captures from `form_outbox`; test records are always read-only. Production enquiries count stored leads. Analytics reads current `analytics_events` with live/legacy source only and excludes preview traffic; consent still controls the existing collector. Dates are UTC; the accepted range is 1–90 days. Leads return the latest 200 at most, bounded below the published adapter's 4 MB limit; `truncated` signals a bounded result. This alpha has no historical pagination/export UI.
62
+
63
+ Status updates allow `new`, `contacted`, or `closed` and require `leads:write` in addition to the admin's authenticated role and CSRF protections. Cross-tenant and test IDs cannot be updated. They do not retry notifications, change recipients or change collection. Existing D1 migrations remain untouched; this API uses the current schema. Review missing migrations separately for older deployments.
64
+
65
+ ## Explicit Cloudflare rollout
66
+
67
+ Use the customer's intended account and inspect `npx wrangler whoami` before any write. The admin defaults to Workers with Static Assets, D1, R2 and Cloudflare Email Service authentication. Its generated production config disables workers.dev and uses a canonical Custom Domain. Keep local and production manifests/resources separate.
68
+
69
+ 1. In the admin directory, run `npm run plan`. Review Worker/resource names, account ID, zone ownership, sender and hostname. Run `npx wrangler d1 create ACME_ADMIN_DB` and `npx wrangler r2 bucket create ACME_ADMIN_ASSETS` only as explicit provisioning steps. Put their actual identifiers into `wrangler.jsonc`; use dedicated resources for this business.
70
+ 2. Back up any existing target database. Review copied numbered migrations; apply only to the admin's intended database with `npx wrangler d1 migrations apply ACME_ADMIN_DB --remote --config wrangler.jsonc`. Do not apply admin migrations to the website backend database.
71
+ 3. Run `npx vitris-admin owner --email OWNER_EMAIL` inside the admin. Review ignored `.vitris/bootstrap-owner.sql`, then apply it with `npx wrangler d1 execute ACME_ADMIN_DB --remote --config wrangler.jsonc --file .vitris/bootstrap-owner.sql`. Existing accounts are not promoted. Each installation owns its users and sessions.
72
+ 4. Complete Cloudflare Email Service sender-domain onboarding and sending availability. Set `AUTH_FROM` and a restricted `AUTH_EMAIL` send binding in the production config. Verify provider/recipient restrictions, real delivery, single-use login and revocation. The alpha's stubbed email tests do not prove live delivery. Never enable production demo login or use local mode in production.
73
+ 5. Merge/install the backend grant and install `HARNESS_API_TOKEN` through secret stdin as above. Verify the deployed backend API independently. If it needs a compatible release, review its impact and owner authorization separately, retaining existing records/accounts and tenant IDs.
74
+ 6. Attach `admin.customer-domain.com` as the generated Worker Custom Domain in the active zone of this account. Verify DNS, TLS and canonical-host checks. Cross-account/external DNS requires a separate reviewed hostname strategy; a CNAME alone does not satisfy this contract.
75
+ 7. Run `npm run doctor` and `npm run build` (dry run), review the configuration/release diff, then explicitly deploy the admin with `npm run deploy`. Verify the canonical HTTPS domain, actual owner login, signed-in permissions, revoked access and authoritative stored records. Record the deployed revision. Public website publication continues through its own consent and release gates.
76
+
77
+ ### Websites without collection
78
+
79
+ A static website without a registered backend has no historical lead or analytics records to import. Prepare a dedicated website backend Worker, D1 schema, R2 and KV bindings (and optional Analytics Engine) from the harness's `cloudflare/` example. Review account/resource ownership, session secret, migrations and tenant/hostname registration before any cloud writes. Keep backend provisioning and deployment separate from the admin database and deployment.
80
+
81
+ Use `vitris forms inspect` and the plan/apply workflow in `docs/CONTACT-FORMS.md` to register approved origins, form schemas, Turnstile, notification sender and recipients. Preserve existing form endpoints until the owner selects the replacement flow. Validate test submissions in isolation first; do not send customer test notifications without authorization. Enable the existing analytics collector only with the site's consent policy and production hostname/tenant mapping. Scaffolding an admin, setting backendOrigin, or binding a subdomain enables none of this automatically.
82
+
83
+ ## Validation
84
+
85
+ `npm run test:admin` runs isolated synthetic fixtures against actual local D1 and the published runtime Worker adapter, including installer plan/apply/recovery, conflicts, stale plans, identity/account isolation, unauthorized/revoked credentials, read-only grants, test separation and preview exclusion. No live challenge or mail is used: assets and backend transport are in-process test bindings; form rows and analytics are explicitly synthetic stored fixtures. `npm run verify:admin` installs all three exact public npm releases in a fresh ignored directory, then reruns acceptance against that runtime. Evidence stays in `artifacts/admin-integration/`. Run the repository's typecheck, full tests and package verification too.
package/docs/CLI.md CHANGED
@@ -6,10 +6,10 @@ The `vitris` CLI (`@tryvitris/website-harness`) provides a unified, operator-fri
6
6
 
7
7
  ## 1. Installation & Binary
8
8
 
9
- After the first registry release, install as a dependency or run via `npx`. Until then use the tarball instructions in [distribution](DISTRIBUTION.md):
9
+ Install the stable release as a dependency or run via `npx`. For local tarballs and managed upgrades, see [distribution](DISTRIBUTION.md):
10
10
 
11
11
  ```bash
12
- npm install --save-dev @tryvitris/website-harness
12
+ npm install --save-dev --save-exact @tryvitris/website-harness@1.0.0
13
13
  npx vitris --help
14
14
  ```
15
15
 
@@ -23,6 +23,12 @@ node bin/vitris.js --help
23
23
 
24
24
  ## 2. Command Reference
25
25
 
26
+ ### `vitris admin setup|status|verify|grant`
27
+
28
+ Prepare a branded sibling business admin with the pinned published `0.1.0-alpha.1` installer. `vitris admin setup --site SITE --dir SIBLING_ADMIN --domain admin.customer-domain.com --website HTTPS_SITE_ORIGIN --tenant EXISTING_TENANT_ID --backend-origin HTTPS_BACKEND --plan` writes a local plan. Review it, then repeat with `--apply` and dedicated environment `VITRIS_ADMIN_API_TOKEN`. Default grants are read-only; explicit `--lead-write` must be included in both steps to grant status updates. No cloud writes occur. Site creation accepts `--admin` to create instructions only.
29
+
30
+ `vitris admin status --site SITE` reports local metadata. `vitris admin verify --site SITE --dir ADMIN` checks the actual backend contract, identities and stored records without exposing PII. `vitris admin grant --dir ADMIN --grants COMPLETE_MAP_FILE --out NEW_IGNORED_FILE` prepares a local hashed grant map while preserving other installations. See [ADMIN.md](ADMIN.md) for preservation rules, API semantics, secret stdin and explicit provisioning/authentication/DNS/deployment steps.
31
+
26
32
  ### `vitris doctor`
27
33
  Runs environment and preflight health checks.
28
34
  ```bash
@@ -195,16 +201,18 @@ vitris preview [--site <dir>] [--port <number>] [--dry-run]
195
201
  ---
196
202
 
197
203
  ### `vitris deploy`
198
- Builds a verified production bundle and deploys it to Cloudflare Pages.
204
+ Builds and verifies locally, then directly uploads the exact staged bundle to Cloudflare Pages. This is the default site deployment path; it does not require GitHub Actions or Cloudflare-hosted builds. The CLI defaults to a preview, while new redesign sites' `npm run deploy` explicitly selects production and `npm run deploy:preview` selects a preview.
199
205
  ```bash
200
- vitris deploy [--site <dir>] [--provider cloudflare] [--environment preview|production] [--branch <branch>] [--dry-run]
206
+ vitris deploy [--site <dir>] [--provider cloudflare] [--environment preview|production] [--branch <branch>] [--quick] [--dry-run]
201
207
  ```
202
208
  Workflow:
203
209
  1. Scoped preflight check verifying Cloudflare credentials (`CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` or `wrangler login`).
204
- 2. Build verified static `dist/` bundle (aborts if build fails or is dirty).
205
- 3. Executes `npx wrangler pages deploy dist --project-name=<slug>`.
210
+ 2. Build and verify the static `dist/` bundle locally, then stage its exact bytes (aborts if verification fails or source/output changes).
211
+ 3. Upload the staged bundle through Wrangler to the configured Pages project and environment; record the source, artifact and deployment identity.
206
212
  4. Executes automated remote smoke check against the deployed `*.pages.dev` URL.
207
213
 
214
+ Quick publish: `vitris deploy --quick --environment production` rebuilds and uploads without graph gates, browser reviews, or launch preflight. New sites also include `npm run deploy:quick`. The CLI still defaults to preview; preservation sites support previews only and quick mode also skips screenshot comparisons. Compilation, Cloudflare credentials, staged-bundle integrity and the remote HTTP smoke check still apply. Receipts use policy `quick-publish-build-only-v1` and results report `verification: "build-only"`. Skipped reviews are never marked passed. Ordinary deployment retains full verification.
215
+
208
216
  ---
209
217
 
210
218
  ### `vitris share`
@@ -1,12 +1,34 @@
1
1
  # Use your own Cloudflare account
2
2
 
3
+ Optional business admins use separate Workers, D1, R2 and Cloudflare Email Service authentication in the customer's intended account. See [ADMIN.md](ADMIN.md) for local `vitris admin setup`, explicit provisioning/owner bootstrap/DNS/migrations/deployment, and deployed backend compatibility checks. Setup never deploys or migrates a shared existing backend.
4
+
3
5
  Local authoring, compilation and preview require no Cloudflare account or API keys. Hosting is an explicit later operation. These examples provision resources in your own account.
4
6
 
5
7
  ## Static customer websites
6
8
 
7
- Create a Cloudflare account. From the customer directory run `npx wrangler login`, check the account with `npx wrangler whoami`, and run `npx wrangler pages project create YOUR_PROJECT`. Set `launch.json.pagesProject` to that name. CI uses your own `CLOUDFLARE_ACCOUNT_ID` and an account-scoped token with Pages Edit access, stored in protected CI secrets. Never put a token in launch.json, HTML, assets or Git.
9
+ The default is to build and verify on the operator's computer and upload the finished bundle directly to Cloudflare Pages. GitHub stores source and history; no GitHub Actions or Cloudflare Git builds are required. New sites ship an inactive hosted-workflow example under `deployment/`, outside `.github/workflows/`.
10
+
11
+ Create a Cloudflare account. From the customer directory run `npx wrangler login`, check the account with `npx wrangler whoami`, and run `npx wrangler pages project create YOUR_PROJECT` to create a Direct Upload project. Set `launch.json.pagesProject` to that name and `launch.json.publicOrigin` to the intended production HTTPS origin. Never put credentials in launch.json, HTML, assets or Git. An unattended operator may use their own `CLOUDFLARE_ACCOUNT_ID` and an account-scoped token with Pages Edit access in ignored environment configuration.
12
+
13
+ After dependency installation and `npx playwright install chromium`, run `npm run deploy:preview` for a hosted preview. After accepting the preview, run `npm run deploy` only when you intend to publish production. These scripts invoke `vitris deploy` with an explicit environment: local build and verification, exact-byte staging, direct upload, deployment receipt, and HTTP smoke check. Ordinary publishing retains the full verification gates. Keep `dist/`, `agent/release-bundles/`, `agent/release-candidate.json`, and `agent/releases/` ignored in Git. Local builds can be repeated without invoking a hosted build service; Cloudflare hosting, API, file and backend quotas still apply.
14
+
15
+ Preservation mode supports temporary previews only; its `npm run deploy` selects preview. Follow PRESERVE.md for its narrower contract. Custom-domain and DNS changes remain separate explicit launch steps. The computer must be online and authenticated during an upload; Cloudflare serves the deployed site independently afterward.
16
+
17
+ ### Adopt local uploads in an existing site
18
+
19
+ Installing a new harness version does not rewrite customer package scripts, authored files, workflow state or remote Cloudflare settings. Review each site's publication contract before making changes, especially if it uses authenticated backend Worker publication.
20
+
21
+ 1. Keep the existing Pages project, domains and `launch.json` settings. For a Git-connected Pages project, turn off automatic production branch deployments and set preview branches to None in Cloudflare's branch controls. Wrangler can still deploy directly to the existing project.
22
+ 2. Review and disable the site's automatic GitHub deployment workflow so source pushes do not create a second publication path. Keep any independently chosen test-only CI.
23
+ 3. Set the site's package scripts to `node ./node_modules/@tryvitris/website-harness/bin/vitris.js deploy --site . --environment production` for `deploy` and the same command with `--environment preview` for `deploy:preview`. Preservation sites must use preview for both. Keep quick publish separate and explicitly requested.
24
+ 4. Add the generated output paths listed above to `.gitignore`, preserving existing rules. Keep source and the lockfile in Git. Moving already tracked output to ignored status requires reviewing the site's index; an ignore rule alone does not untrack files.
25
+ 5. Authenticate with the site's own Cloudflare account, accept a direct-upload preview, then publish production only when requested. Check the receipt and hosted smoke result.
26
+
27
+ See Cloudflare's [Direct Upload guide](https://developers.cloudflare.com/pages/get-started/direct-upload/) and [disabling automatic Git deployments](https://developers.cloudflare.com/pages/configuration/git-integration/#disable-automatic-deployments).
28
+
29
+ ### Optional hosted automation
8
30
 
9
- Run `npm run build` and `npm run preflight` locally. Run `npm run deploy` only when you intend to upload. Accept the hosted preview before separate custom-domain and DNS changes. Preservation mode supports temporary previews; follow PRESERVE.md for its narrower contract.
31
+ An operator may explicitly choose hosted builds. To use GitHub Actions, review and copy `deployment/github-actions.yml.example` into `.github/workflows/deploy.yml` and configure protected credentials. The example retains production/preview preflight and authenticated backend bundle signing where configured. Hosted CI uses the selected provider's allowance. Cloudflare Git integration is another opt-in alternative; its build must install Chromium and run the required site preflight before publication. Enable one publication path for each site.
10
32
 
11
33
  ## Optional backend Worker
12
34
 
@@ -51,3 +73,6 @@ Cloudflare references: [configuration](https://developers.cloudflare.com/workers
51
73
  The Worker preview GitHub workflow is disabled by default. A repository owner may opt in with the `VITRIS_WORKER_PREVIEW_ENABLED=true` repository variable after provisioning their own isolated preview resources and GitHub secrets. No account credentials are included in source.
52
74
 
53
75
  Template library maintainers also configure their own `VITRIS_TEMPLATE_ORIGIN`, `VITRIS_TEMPLATE_BUCKET`, R2 S3 endpoint, and access credentials; see `agent/refs/template-library.md`. Static-site users can use the public gallery without those credentials.
76
+
77
+
78
+ For an explicitly requested quick publish, use `vitris deploy --quick --environment production` (`npm run deploy:quick` in newly scaffolded sites). This rebuilds and deploys without browser, graph or launch review gates. Compilation, Cloudflare credentials, staged-file integrity and an HTTP smoke check still run. Receipts record build-only verification. Preservation sites use `--environment preview` and also skip screenshot comparisons. Ordinary deployment retains full preflight.
@@ -8,6 +8,8 @@ Generate a separate directory for each customer with `vitris site create`. Open
8
8
 
9
9
  New sites depend on the exact creating package version, avoiding paths into an ephemeral `npx` cache. Before a registry release, pass `--harness` with a tarball path or an explicit `file:` dependency. Both paths are relative to the generated site directory. Registry and tarball installations include bundled JavaScript commands and APIs; consumers do not need to strip TypeScript inside `node_modules`.
10
10
 
11
+ New sites build and verify locally and upload directly to Cloudflare Pages using `npm run deploy:preview` or an explicitly requested production `npm run deploy`. No active GitHub deployment workflow is scaffolded. `deployment/github-actions.yml.example` is an optional hosted alternative. Existing site scripts, workflows and remote project settings are not changed by installing or upgrading the harness; follow the migration steps in [Cloudflare setup](CLOUDFLARE.md). Keep generated output out of source control.
12
+
11
13
  ## Terminology and compatibility
12
14
 
13
15
  | Current name | Accepted legacy name |
@@ -27,7 +29,7 @@ At the same configuration level, current names take precedence. CLI build overri
27
29
  Stop its workflow first. From the harness checkout, preview changes:
28
30
 
29
31
  ```bash
30
- node bin/vitris-migrate-site.js --site ../acme --harness ../vitris-harness/tryvitris-website-harness-0.1.0-beta.7.tgz
32
+ node bin/vitris-migrate-site.js --site ../acme --harness ../vitris-harness/tryvitris-website-harness-1.0.0.tgz
31
33
  ```
32
34
 
33
35
  Add `--apply` to perform the displayed changes. The command backs up affected files under the client's `agent-backups/`, renames the package dependency and known script paths, and converts the backend origin key. Conflicting old/new origins fail before writes. Client pages, components, media, secrets, existing lockfile, and workflow state are preserved. Repeating it makes no further edits.
@@ -59,7 +61,7 @@ These are rollout steps, not completed migrations. This package does not automat
59
61
 
60
62
  ## Public release preparation
61
63
 
62
- The owner selected MIT and public npm publication under `@tryvitris/website-harness`. The `prepublishOnly` guard verifies the package identity, public registry and visibility, beta dist-tag, and packed-release audit before allowing publication. See SECURITY.md for the release audit and CLOUDFLARE.md for user-owned infrastructure.
64
+ The owner selected MIT and public npm publication under `@tryvitris/website-harness`. Version `1.0.0` is the first stable release, published with the `latest` dist-tag. The `prepublishOnly` guard verifies the package identity, public registry and visibility, the `latest` tag for stable versions (`beta` for prereleases), and the packed-release audit before allowing publication. See SECURITY.md for the release audit and CLOUDFLARE.md for user-owned infrastructure.
63
65
 
64
66
  MIT licensing and intended repository metadata are included. Before public release, review third-party provenance and dependency notices, confirm npm scope ownership/authentication, and repeat the source, Git-history, and tarball credential checks. The dedicated `vitris-harness` repository starts with fresh history. Keep the original private development repository and customer repositories private. Creating a remote repository, changing visibility, and publishing npm are separate explicitly authorized operations.
65
67
 
@@ -67,4 +69,4 @@ Run `npm run test:freeze` after final source edits. It checks type safety, tests
67
69
 
68
70
  ## Optional corrected teaching data
69
71
 
70
- The core npm package includes the original v1/v2 teaching studies and reference metadata. The larger immutable corrected studies (v3/v4, releases 2026-10-06.1 and 2026-10-06.2) are optional data, supplied separately from the core beta. They retain their original bytes and hashes; the package does not substitute reduced images or waive inspection. Set VITRIS_REFERENCE_DATA to a verified data root containing design-system/compositions/v3 and v4 before opting into those releases through launch.json.designReferences. A source checkout can serve as that root. Missing data produces an explicit error. The ordinary new-site workflow does not opt into those corrected teaching releases.
72
+ The core npm package includes the original v1/v2 teaching studies and reference metadata. The larger immutable corrected studies (v3/v4, releases 2026-10-06.1 and 2026-10-06.2) are optional data, supplied separately from the core package. They retain their original bytes and hashes; the package does not substitute reduced images or waive inspection. Set VITRIS_REFERENCE_DATA to a verified data root containing design-system/compositions/v3 and v4 before opting into those releases through launch.json.designReferences. A source checkout can serve as that root. Missing data produces an explicit error. The ordinary new-site workflow does not opt into those corrected teaching releases.
package/docs/ENGINE.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Engine API and local refinement
2
2
 
3
+ The harness includes the full Vitris icon catalog, motion recipes/runtime, and optional analytics. Agent guidance lives in `agent/refs/icons.md`, `motion.md`, `analytics.md`, and `performance.md`, loaded by the relevant workflow stages. Icons compile to only the selected inline SVGs; no icon catalog or font reaches the browser. Motion uses the measured engine recorded in `docs/scroll-motion-engine.json`, bundled and minified into a self-hosted asset requested only by active motion routes. The current engine is vanilla JavaScript; third-party animation engines are not required by sites.
4
+
5
+ Static builds compile source pages once, deduplicate identical content-addressed CSS/islands, and select assets per route. The generated cookie preference page gets base styles and its first-party beacon without site widgets or motion. Compatibility `site.css`/`islands.js` files remain available, while authored routes reference their selected bundles. `buildSite()` returns the files actually written, including route assets and excluding the beacon when no backend is configured.
6
+
7
+ `launch.json.backendOrigin` connects first-party analytics (visits, attribution, engagement, contact clicks, accepted form conversions and presence); collection requires a configured backend and registered site. Optional `webAnalyticsToken` adds Cloudflare field-performance tracking on production pages. Tracking configuration does not provision services or imply measured results. See the analytics reference for selectors, preferences and test practices. The package smoke check renders every supported icon variant from an installed tarball and compares its coverage with source.
8
+
3
9
  Install an exact `@tryvitris/website-harness` dependency in each website. `@tryvitris/website-harness/contracts` is browser-safe validation; `@tryvitris/website-harness/engine` executes Node filesystem operations. Legacy `@tryvitris/website-harness/cli/api` exports remain available.
4
10
 
5
11
  ```js
package/docs/PRESERVE.md CHANGED
@@ -24,7 +24,7 @@ Verification compares every captured route at 1440px and 390px against hashed so
24
24
 
25
25
  Contact forms use the shared `/api/leads` service only after explicit server registration and public `launch.json.forms` bindings. `backendOrigin` alone does not enable submissions or notifications. The old `number` field maps to the compatible phone column while retaining its authored HTML name. Default previews validate locally and display a notice. The shared runtime adds a security challenge on submission and accessible feedback while preserving layouts and fields. Verification separates resting-page fidelity from mocked challenge/submission states and sends no customer inquiries. See [CONTACT-FORMS.md](CONTACT-FORMS.md) for sandbox setup, provisioning, server readiness, delivery semantics and the separately authorized rollout. Legacy analytics and employee portal services are not migrated. External navigation links, including employee-login links, remain links to their existing destinations.
26
26
 
27
- Deployment requires `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN` with Pages Edit permission. The harness inspects or creates the Pages project, verifies that the preview branch differs from its production branch, stages hashed verified bytes, uploads them, and repeats browser checks against the returned `pages.dev` URL. A newly created project uses `production` as its reserved production branch. No customer domains or DNS records are changed. Preview responses carry `noindex`; previews are public and do not expire automatically. The generated CI workflow is manual and preview-only.
27
+ Deployment requires `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN` with Pages Edit permission. The harness inspects or creates the Pages project, verifies that the preview branch differs from its production branch, stages hashed verified bytes, uploads them, and repeats browser checks against the returned `pages.dev` URL. A newly created project uses `production` as its reserved production branch. No customer domains or DNS records are changed. Preview responses carry `noindex`; previews are public and do not expire automatically. Local builds and direct uploads are the default. The inactive deployment/github-actions.yml.example can be installed explicitly for manual, preview-only hosted automation.
28
28
 
29
29
  Initial availability checks retry transient hosting failures. If Cloudflare has accepted the upload but its preview is not reachable yet, keep the returned URL and recheck it with `vitris verify --site DIR --remote https://HASH.PROJECT.pages.dev`. This reruns the hosted browser checks without uploading another deployment. Local and remote reports are separate.
30
30
 
package/docs/SECURITY.md CHANGED
@@ -10,13 +10,13 @@ Customer HTML never renders on an admin origin. Configure a dedicated PREVIEW_HO
10
10
 
11
11
  ## Package auditing
12
12
 
13
- The npm beta uses an explicit file allowlist. Local credentials, operator configuration, customer captures, tests, historical archives, plans and runtime receipts are excluded. esbuild receives no secret-valued environment definitions. Integrations read the installing user's environment or Worker secret bindings.
13
+ The npm package uses an explicit file allowlist. Local credentials, operator configuration, customer captures, tests, historical archives, plans and runtime receipts are excluded. esbuild receives no secret-valued environment definitions. Integrations read the installing user's environment or Worker secret bindings.
14
14
 
15
15
  `npm pack` builds and runs audit:package. The audit opens the actual tarball, checks every filename, detects common provider tokens/private keys/credential URLs, rejects known operator infrastructure IDs, and compares bytes against credential values available in the process environment and local credential files, including encoded forms. Reports contain file locations and rule names, never matched values. Exact-value checking covers only credentials accessible to the process; it cannot establish the absence of unknown keys.
16
16
 
17
17
  Install a verified Gitleaks release binary and set GITLEAKS_BIN to its executable before `npm run audit:package`. This independent detection layer is required by release CI. Use full redaction and archive/decoding inspection. Re-audit after any source, build, dependency or content change. Keep the final tarball SHA-256 and audit report privately under artifacts/.
18
18
 
19
- The prepublishOnly guard verifies the public @tryvitris/website-harness identity, registry, visibility, prerelease tag, and packed-release audit. No workflow publishes packages. Releases require owner authorization and verification of the final source and tarball. Prefer npm trusted publishing for automated releases; interactive local releases use the maintainer's npm login and 2FA.
19
+ The prepublishOnly guard verifies the public @tryvitris/website-harness identity, registry, visibility, `latest` tag for stable versions (`beta` for prereleases), and packed-release audit. No workflow publishes packages. Releases require owner authorization and verification of the final source and tarball. Prefer npm trusted publishing for automated releases; interactive local releases use the maintainer's npm login and 2FA.
20
20
 
21
21
  Before making a repository public, separately scan all Git history and uncommitted public source. A clean npm package does not make existing history safe. Historical archives and customer experiments stay private. Never rewrite frozen baselines to remove findings. Revoke/rotate any real disclosed credential with its provider and address repository history separately.
22
22
 
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@tryvitris/website-harness",
3
- "version": "0.1.0-beta.7",
3
+ "version": "1.0.0",
4
4
  "description": "Vitris agent harness for building and verifying customer websites, with a static compiler, media tools, and optional Cloudflare backend.",
5
5
  "type": "module",
6
6
  "exports": {
7
- "./icons": {
8
- "types": "./bin/types/src/icons/index.d.ts",
9
- "import": "./bin/api/icons.js"
10
- },
7
+ "./icons": {
8
+ "types": "./bin/types/src/icons/index.d.ts",
9
+ "import": "./bin/api/icons.js"
10
+ },
11
11
  ".": {
12
12
  "types": "./bin/types/src/build/index.d.ts",
13
13
  "import": "./bin/api/index.js"
@@ -94,9 +94,9 @@
94
94
  "vitris-templates": "bin/vitris-templates.js",
95
95
  "vitris-motion-view": "bin/vitris-motion-view.js",
96
96
  "vitris-media-serve": "bin/vitris-media-serve.js",
97
- "vitris-cursor-hook": "bin/vitris-cursor-hook.js",
98
- "vitris-icons": "bin/vitris-icons.js",
99
- "vitris-verify-performance": "bin/vitris-verify-performance.js"
97
+ "vitris-cursor-hook": "bin/vitris-cursor-hook.js",
98
+ "vitris-icons": "bin/vitris-icons.js",
99
+ "vitris-verify-performance": "bin/vitris-verify-performance.js"
100
100
  },
101
101
  "files": [
102
102
  "bin/**/*.js",
@@ -106,6 +106,7 @@
106
106
  "design-system/MASTER.md",
107
107
  "design-system/knowledge",
108
108
  "docs/CLI.md",
109
+ "docs/ADMIN.md",
109
110
  "docs/DISTRIBUTION.md",
110
111
  "docs/ENGINE.md",
111
112
  "docs/CLOUDFLARE.md",
@@ -147,7 +148,9 @@
147
148
  "preview:prepare": "node scripts/prepare-worker-preview.mjs",
148
149
  "preview:worker": "wrangler preview --config .wrangler-preview.jsonc --ignore-base-config",
149
150
  "typecheck": "tsc --noEmit",
150
- "test": "node --experimental-strip-types --test --test-concurrency=4 src/icons.test.ts src/template-icon-migration.test.ts src/engine.test.ts src/upgrade.test.ts src/hosting.test.ts src/render.test.ts src/analytics.test.ts src/cookie-compliance.test.ts src/schema.test.ts src/patch.test.ts src/jobs.test.ts src/onboard.test.ts src/github-preview.test.ts src/agent.test.ts src/workflow.test.ts src/design-run.test.ts src/creative-profile.test.ts src/creative-efficiency.test.ts src/refine.test.ts src/critic-calibration.test.ts src/cli.test.ts src/jev.test.ts src/lifecycle.test.ts src/theme-lifecycle-policy.test.ts src/template-adaptation.test.ts src/adaptation-checkpoint.test.ts src/template-motion.test.ts src/template-motion-browser.test.ts src/experience-browser.test.ts src/jev-capabilities.test.ts src/jev-phase8.test.ts src/jev-prepilot.test.ts src/jev-phase0.test.ts src/jev-sept20.test.ts src/trace.test.ts src/cursor-hook.test.ts src/design-intelligence.test.ts src/design-context-integration.test.ts src/package-bin.test.ts src/knowledge-layers.test.ts src/launch-preflight.test.ts src/page-transfer.test.ts src/worker-publish.test.ts src/worker-preview.test.ts src/worker-security.test.ts src/harness-upgrades.test.ts src/stock-media.test.ts src/harness-distribution.test.ts src/storyboard-media.test.ts src/added-media.test.ts src/lead-forms.test.ts src/composition.test.ts src/reference-library.test.ts src/art-direction.test.ts src/scroll-motion.test.ts src/scroll-motion-browser.test.ts src/artistic-motion-browser.test.ts src/page-composition.test.ts src/reference-quality.test.ts src/production-quality.test.ts src/browser-focus.test.ts src/browser-work-queue.test.ts src/quality-subject.test.ts src/preview-cli.test.ts src/theme-selection.test.ts src/site-inputs.test.ts src/fieldwell.test.ts src/still-field.test.ts src/current-craft.test.ts src/copper-chair.test.ts src/clearline.test.ts src/template-cloud.test.ts src/contact-forms.test.ts src/contact-forms-operations.test.ts src/contact-forms-browser.test.ts src/preserve.test.ts src/release-safety.test.ts src/performance-media.test.ts src/lighthouse-browser.test.ts src/browser-timeout.test.ts src/browser-output-contract.test.ts src/template-motion-snapshot.test.ts",
151
+ "test:admin": "node --experimental-strip-types --test src/admin-integration.test.ts",
152
+ "verify:admin": "node --experimental-strip-types scripts/verify-admin.ts",
153
+ "test": "node --experimental-strip-types --test --test-concurrency=2 src/admin-integration.test.ts src/icons.test.ts src/template-icon-migration.test.ts src/engine.test.ts src/upgrade.test.ts src/hosting.test.ts src/render.test.ts src/analytics.test.ts src/cookie-compliance.test.ts src/schema.test.ts src/patch.test.ts src/jobs.test.ts src/onboard.test.ts src/github-preview.test.ts src/agent.test.ts src/workflow.test.ts src/design-run.test.ts src/creative-profile.test.ts src/creative-efficiency.test.ts src/refine.test.ts src/critic-calibration.test.ts src/cli.test.ts src/jev.test.ts src/lifecycle.test.ts src/theme-lifecycle-policy.test.ts src/template-adaptation.test.ts src/adaptation-checkpoint.test.ts src/template-motion.test.ts src/template-motion-browser.test.ts src/experience-browser.test.ts src/jev-capabilities.test.ts src/jev-phase8.test.ts src/jev-prepilot.test.ts src/jev-phase0.test.ts src/jev-sept20.test.ts src/trace.test.ts src/cursor-hook.test.ts src/design-intelligence.test.ts src/design-context-integration.test.ts src/package-bin.test.ts src/knowledge-layers.test.ts src/launch-preflight.test.ts src/page-transfer.test.ts src/worker-publish.test.ts src/worker-preview.test.ts src/worker-security.test.ts src/harness-upgrades.test.ts src/stock-media.test.ts src/harness-distribution.test.ts src/storyboard-media.test.ts src/added-media.test.ts src/lead-forms.test.ts src/composition.test.ts src/reference-library.test.ts src/art-direction.test.ts src/scroll-motion.test.ts src/scroll-motion-browser.test.ts src/artistic-motion-browser.test.ts src/page-composition.test.ts src/reference-quality.test.ts src/production-quality.test.ts src/browser-focus.test.ts src/browser-work-queue.test.ts src/quality-subject.test.ts src/preview-cli.test.ts src/theme-selection.test.ts src/site-inputs.test.ts src/fieldwell.test.ts src/still-field.test.ts src/current-craft.test.ts src/copper-chair.test.ts src/clearline.test.ts src/template-cloud.test.ts src/contact-forms.test.ts src/contact-forms-operations.test.ts src/contact-forms-browser.test.ts src/preserve.test.ts src/release-safety.test.ts src/performance-media.test.ts src/lighthouse-browser.test.ts src/browser-timeout.test.ts src/browser-output-contract.test.ts src/template-motion-snapshot.test.ts",
151
154
  "eval:jev": "node --experimental-strip-types scripts/eval-jev.ts",
152
155
  "benchmark": "node --experimental-strip-types scripts/benchmark.ts",
153
156
  "refresh-agent": "node --experimental-strip-types scripts/refresh-agent.ts",
@@ -169,15 +172,15 @@
169
172
  "templates:gallery": "node --experimental-strip-types scripts/template-gallery.ts",
170
173
  "templates:artifact": "node --experimental-strip-types scripts/template-cloud-artifact.ts",
171
174
  "audit:package": "node scripts/audit-package.mjs",
172
- "prepublishOnly": "node scripts/guard-publish.mjs",
173
- "icons": "node --experimental-strip-types scripts/icons.ts",
174
- "icons:artifact": "node --experimental-strip-types scripts/icons.ts gallery",
175
- "icons:gallery": "node --experimental-strip-types scripts/icons.ts gallery --serve",
176
- "test:icons": "node --experimental-strip-types --test src/icons.test.ts",
177
- "verify:icons": "node --experimental-strip-types scripts/verify-icons.ts",
178
- "icons:review-industry-studio": "node --experimental-strip-types scripts/review-industry-studio.ts",
179
- "templates:icons": "node --experimental-strip-types scripts/migrate-template-icons.ts",
180
- "verify:performance": "node --experimental-strip-types scripts/verify-performance.ts"
175
+ "prepublishOnly": "node scripts/guard-publish.mjs",
176
+ "icons": "node --experimental-strip-types scripts/icons.ts",
177
+ "icons:artifact": "node --experimental-strip-types scripts/icons.ts gallery",
178
+ "icons:gallery": "node --experimental-strip-types scripts/icons.ts gallery --serve",
179
+ "test:icons": "node --experimental-strip-types --test src/icons.test.ts",
180
+ "verify:icons": "node --experimental-strip-types scripts/verify-icons.ts",
181
+ "icons:review-industry-studio": "node --experimental-strip-types scripts/review-industry-studio.ts",
182
+ "templates:icons": "node --experimental-strip-types scripts/migrate-template-icons.ts",
183
+ "verify:performance": "node --experimental-strip-types scripts/verify-performance.ts"
181
184
  },
182
185
  "engines": {
183
186
  "node": ">=24"
@@ -192,13 +195,15 @@
192
195
  },
193
196
  "dependencies": {
194
197
  "@axe-core/playwright": "4.11.0",
198
+ "@tryvitris/website-admin-contracts": "0.1.0-alpha.1",
199
+ "@tryvitris/website-admin-harness": "0.1.0-alpha.1",
195
200
  "@typesafe-ai/sdk": "^0.6.0",
196
201
  "blake3-wasm": "^2.1.5",
202
+ "chrome-launcher": "1.2.1",
203
+ "lighthouse": "13.5.0",
197
204
  "parse5": "8.0.0",
198
- "playwright": "^1.63.0",
199
- "chrome-launcher": "1.2.1",
200
- "lighthouse": "13.5.0",
201
- "sharp": "0.35.5"
205
+ "playwright": "^1.63.0",
206
+ "sharp": "0.35.5"
202
207
  },
203
208
  "overrides": {
204
209
  "miniflare": {
@@ -218,7 +223,7 @@
218
223
  },
219
224
  "publishConfig": {
220
225
  "access": "public",
221
- "tag": "beta",
226
+ "tag": "latest",
222
227
  "registry": "https://registry.npmjs.org/"
223
228
  }
224
229
  }