@wix/agent-skills 1.36.0 → 1.36.1

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 (776) hide show
  1. package/package.json +8 -3
  2. package/skills/wix-headless-kit/install/pins.json +1 -1
  3. package/skills/wix-manage/SKILL.md +3 -3
  4. package/skills/wix-manage/references/cms/cms-data-items-crud.md +78 -1
  5. package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +11 -11
  6. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +20 -51
  7. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +4 -4
  8. package/skills/wix-base44-connector/SKILL.md +0 -437
  9. package/skills/wix-base44-connector/references/CAPABILITY_MAP.md +0 -78
  10. package/skills/wix-base44-connector/scripts/utils.cjs +0 -466
  11. package/skills/wix-export/SKILL.md +0 -83
  12. package/skills/wix-harmony-editor/.publish-manifest.json +0 -8
  13. package/skills/wix-harmony-editor/COPY-SITE.md +0 -494
  14. package/skills/wix-harmony-editor/SKILL.md +0 -317
  15. package/skills/wix-harmony-editor/scripts/copy/build-description.mjs +0 -249
  16. package/skills/wix-harmony-editor/scripts/copy/check-description.mjs +0 -225
  17. package/skills/wix-harmony-editor/scripts/copy/check-mirror.mjs +0 -89
  18. package/skills/wix-harmony-editor/scripts/copy/compare-preview.mjs +0 -76
  19. package/skills/wix-harmony-editor/scripts/copy/deploy-description.mjs +0 -212
  20. package/skills/wix-harmony-editor/scripts/copy/desc-hash.mjs +0 -44
  21. package/skills/wix-harmony-editor/scripts/copy/editor-run.mjs +0 -45
  22. package/skills/wix-harmony-editor/scripts/copy/export-page.mjs +0 -53
  23. package/skills/wix-harmony-editor/scripts/copy/find-interactions.mjs +0 -76
  24. package/skills/wix-harmony-editor/scripts/copy/hide-scrollbars.mjs +0 -16
  25. package/skills/wix-harmony-editor/scripts/copy/import-media.mjs +0 -150
  26. package/skills/wix-harmony-editor/scripts/copy/link-url.mjs +0 -27
  27. package/skills/wix-harmony-editor/scripts/copy/lint-api.mjs +0 -56
  28. package/skills/wix-harmony-editor/scripts/copy/measure-source.mjs +0 -211
  29. package/skills/wix-harmony-editor/scripts/copy/merge-mirrors.mjs +0 -29
  30. package/skills/wix-harmony-editor/scripts/copy/mirror-site.mjs +0 -92
  31. package/skills/wix-harmony-editor/scripts/copy/mobile-stage.mjs +0 -56
  32. package/skills/wix-harmony-editor/scripts/copy/preview-widths.mjs +0 -73
  33. package/skills/wix-harmony-editor/scripts/copy/render-plate.mjs +0 -67
  34. package/skills/wix-harmony-editor/scripts/copy/serve-mirror.mjs +0 -102
  35. package/skills/wix-harmony-editor/scripts/copy/snapshot-capabilities.mjs +0 -40
  36. package/skills/wix-harmony-editor/scripts/copy/split-sections.mjs +0 -191
  37. package/skills/wix-harmony-editor/scripts/copy/upload-media-manager.mjs +0 -61
  38. package/skills/wix-harmony-editor/scripts/launch.sh +0 -359
  39. package/skills/wix-headless/SKILL.md +0 -151
  40. package/skills/wix-headless/references/AI_FEATURES.md +0 -178
  41. package/skills/wix-headless/references/CAPABILITIES.md +0 -117
  42. package/skills/wix-headless/references/CONTENT.md +0 -36
  43. package/skills/wix-headless/references/DESIGN.md +0 -55
  44. package/skills/wix-headless/references/DISCOVERY.md +0 -80
  45. package/skills/wix-headless/references/DOC_DISCOVERY.md +0 -43
  46. package/skills/wix-headless/references/FEEDBACK.md +0 -129
  47. package/skills/wix-headless/references/IMAGE_GENERATION.md +0 -80
  48. package/skills/wix-headless/references/SDK_HANDOFF.md +0 -108
  49. package/skills/wix-headless/references/SEED.md +0 -74
  50. package/skills/wix-headless/references/SETUP.md +0 -60
  51. package/skills/wix-headless/references/astro.md +0 -98
  52. package/skills/wix-headless/references/inline-recipes/experience-donations.md +0 -102
  53. package/skills/wix-headless/references/inline-recipes/experience-store.md +0 -49
  54. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +0 -196
  55. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +0 -590
  56. package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +0 -279
  57. package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +0 -163
  58. package/skills/wix-headless/references/inline-recipes/how-to-code-donations.md +0 -146
  59. package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +0 -203
  60. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +0 -696
  61. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +0 -124
  62. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +0 -160
  63. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +0 -118
  64. package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +0 -132
  65. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +0 -126
  66. package/skills/wix-headless/references/inline-recipes/how-to-code-rentals.md +0 -254
  67. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +0 -191
  68. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +0 -213
  69. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +0 -161
  70. package/skills/wix-headless/references/inline-recipes/setup-blog.md +0 -175
  71. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +0 -232
  72. package/skills/wix-headless/references/inline-recipes/setup-cms.md +0 -200
  73. package/skills/wix-headless/references/inline-recipes/setup-donations.md +0 -15
  74. package/skills/wix-headless/references/inline-recipes/setup-events.md +0 -196
  75. package/skills/wix-headless/references/inline-recipes/setup-forms.md +0 -288
  76. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +0 -214
  77. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +0 -155
  78. package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +0 -229
  79. package/skills/wix-headless/references/inline-recipes/setup-rentals.md +0 -254
  80. package/skills/wix-headless/references/inline-recipes/setup-restaurant-experiences.md +0 -73
  81. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +0 -197
  82. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +0 -136
  83. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +0 -152
  84. package/skills/wix-headless/references/managed/AUTHENTICATION.md +0 -71
  85. package/skills/wix-headless/references/managed/CONNECT.md +0 -74
  86. package/skills/wix-headless/references/managed/CREATE.md +0 -149
  87. package/skills/wix-headless/references/managed/DEPLOYMENT.md +0 -104
  88. package/skills/wix-headless/references/non-astro.md +0 -59
  89. package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +0 -22
  90. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +0 -15
  91. package/skills/wix-headless/references/stripe/AUTHENTICATION.md +0 -55
  92. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +0 -71
  93. package/skills/wix-headless/scripts/bootstrap.mjs +0 -156
  94. package/skills/wix-headless-replatform/.publish-manifest.json +0 -8
  95. package/skills/wix-headless-replatform/SKILL.md +0 -116
  96. package/skills/wix-headless-replatform/agents/openai.yaml +0 -6
  97. package/skills/wix-headless-replatform/references/control-and-visual-fidelity-contract.md +0 -43
  98. package/skills/wix-headless-replatform/references/extraction-schema.md +0 -187
  99. package/skills/wix-headless-replatform/references/interaction-runtime-contract.md +0 -137
  100. package/skills/wix-headless-replatform/references/layout-blueprint-contract.md +0 -41
  101. package/skills/wix-headless-replatform/references/output-contract.md +0 -93
  102. package/skills/wix-headless-replatform/references/post-build-gap-contract.md +0 -125
  103. package/skills/wix-headless-replatform/references/qa-checklist.md +0 -83
  104. package/skills/wix-headless-replatform/references/safety.md +0 -19
  105. package/skills/wix-headless-replatform/references/ui-normalization-contract.md +0 -70
  106. package/skills/wix-headless-replatform/references/workflow.md +0 -157
  107. package/skills/wix-headless-replatform/registry/README.md +0 -20
  108. package/skills/wix-headless-replatform/registry/approvals/button/shadcn-default-ac60ef5.json +0 -28
  109. package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/button.tsx +0 -54
  110. package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/capabilities.json +0 -60
  111. package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/contract.md +0 -48
  112. package/skills/wix-headless-replatform/registry/licenses/shadcn-ui-ac60ef5-MIT.txt +0 -21
  113. package/skills/wix-headless-replatform/registry/registry.json +0 -36
  114. package/skills/wix-headless-replatform/resources/rp-facelift/SKILL.md +0 -32
  115. package/skills/wix-headless-replatform/resources/rp-project-context/SKILL.md +0 -62
  116. package/skills/wix-headless-replatform/resources/rp-qa-gap-loop/SKILL.md +0 -64
  117. package/skills/wix-headless-replatform/resources/rp-source-evidence/SKILL.md +0 -42
  118. package/skills/wix-headless-replatform/resources/rp-ui-implementation/SKILL.md +0 -73
  119. package/skills/wix-headless-replatform/schemas/build-plan.schema.json +0 -10
  120. package/skills/wix-headless-replatform/schemas/candidate.schema.json +0 -19
  121. package/skills/wix-headless-replatform/schemas/common.schema.json +0 -33
  122. package/skills/wix-headless-replatform/schemas/decision-patch.schema.json +0 -10
  123. package/skills/wix-headless-replatform/schemas/decision-request.schema.json +0 -10
  124. package/skills/wix-headless-replatform/schemas/extraction-gap.schema.json +0 -28
  125. package/skills/wix-headless-replatform/schemas/extraction-manifest.schema.json +0 -34
  126. package/skills/wix-headless-replatform/schemas/final-report.schema.json +0 -10
  127. package/skills/wix-headless-replatform/schemas/foundation.schema.json +0 -11
  128. package/skills/wix-headless-replatform/schemas/metadata.schema.json +0 -11
  129. package/skills/wix-headless-replatform/schemas/observation-packet.schema.json +0 -17
  130. package/skills/wix-headless-replatform/schemas/page-capture.schema.json +0 -11
  131. package/skills/wix-headless-replatform/schemas/page-resolution.schema.json +0 -33
  132. package/skills/wix-headless-replatform/schemas/shared-chrome.schema.json +0 -11
  133. package/skills/wix-headless-replatform/schemas/unit.schema.json +0 -40
  134. package/skills/wix-headless-replatform/scripts/assemble-extraction.mjs +0 -844
  135. package/skills/wix-headless-replatform/scripts/benchmark-extraction.mjs +0 -163
  136. package/skills/wix-headless-replatform/scripts/browser-extraction-preflight.mjs +0 -42
  137. package/skills/wix-headless-replatform/scripts/build-extracted-homepage.mjs +0 -228
  138. package/skills/wix-headless-replatform/scripts/clear-wix-starter.mjs +0 -87
  139. package/skills/wix-headless-replatform/scripts/create-wix-project.mjs +0 -505
  140. package/skills/wix-headless-replatform/scripts/discover-urls.mjs +0 -142
  141. package/skills/wix-headless-replatform/scripts/extract-assets.mjs +0 -140
  142. package/skills/wix-headless-replatform/scripts/extract-design-system.mjs +0 -637
  143. package/skills/wix-headless-replatform/scripts/extract-interactions.mjs +0 -1903
  144. package/skills/wix-headless-replatform/scripts/extract-page.mjs +0 -2461
  145. package/skills/wix-headless-replatform/scripts/extract-seo.mjs +0 -25
  146. package/skills/wix-headless-replatform/scripts/extract-tokens.mjs +0 -63
  147. package/skills/wix-headless-replatform/scripts/finalize-extraction-report.mjs +0 -126
  148. package/skills/wix-headless-replatform/scripts/finalize-gap-review.mjs +0 -180
  149. package/skills/wix-headless-replatform/scripts/finalize-gap-review.test.mjs +0 -98
  150. package/skills/wix-headless-replatform/scripts/finalize-migration-website.mjs +0 -103
  151. package/skills/wix-headless-replatform/scripts/generate-control-state-contract.mjs +0 -176
  152. package/skills/wix-headless-replatform/scripts/generate-design-md.mjs +0 -261
  153. package/skills/wix-headless-replatform/scripts/generate-extraction-validators.mjs +0 -25
  154. package/skills/wix-headless-replatform/scripts/generate-invoice-download-backend.mjs +0 -342
  155. package/skills/wix-headless-replatform/scripts/generate-layout-blueprint.mjs +0 -140
  156. package/skills/wix-headless-replatform/scripts/generate-repeater-cms.mjs +0 -22
  157. package/skills/wix-headless-replatform/scripts/generate-route-plan.mjs +0 -143
  158. package/skills/wix-headless-replatform/scripts/generate-scene-contract.mjs +0 -288
  159. package/skills/wix-headless-replatform/scripts/generate-ui-normalization.mjs +0 -266
  160. package/skills/wix-headless-replatform/scripts/generate-visual-assets.mjs +0 -111
  161. package/skills/wix-headless-replatform/scripts/lib/browser-tooling.mjs +0 -570
  162. package/skills/wix-headless-replatform/scripts/lib/common.mjs +0 -329
  163. package/skills/wix-headless-replatform/scripts/lib/component-capabilities.mjs +0 -121
  164. package/skills/wix-headless-replatform/scripts/lib/component-registry.mjs +0 -282
  165. package/skills/wix-headless-replatform/scripts/lib/content-boundary.mjs +0 -61
  166. package/skills/wix-headless-replatform/scripts/lib/extraction-contract.mjs +0 -374
  167. package/skills/wix-headless-replatform/scripts/lib/extraction-detectors.mjs +0 -243
  168. package/skills/wix-headless-replatform/scripts/lib/extraction-validators.generated.mjs +0 -1139
  169. package/skills/wix-headless-replatform/scripts/lib/font-contract.mjs +0 -326
  170. package/skills/wix-headless-replatform/scripts/lib/frontend-automation-state.mjs +0 -184
  171. package/skills/wix-headless-replatform/scripts/lib/gap-analysis.mjs +0 -396
  172. package/skills/wix-headless-replatform/scripts/lib/html-extract.mjs +0 -168
  173. package/skills/wix-headless-replatform/scripts/lib/interaction-bootstrap.mjs +0 -10
  174. package/skills/wix-headless-replatform/scripts/lib/interaction-runtime.mjs +0 -194
  175. package/skills/wix-headless-replatform/scripts/lib/interaction-timeline.mjs +0 -348
  176. package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/classifiers.mjs +0 -141
  177. package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/geometry.mjs +0 -43
  178. package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/vocabulary.mjs +0 -18
  179. package/skills/wix-headless-replatform/scripts/lib/ui-normalization.css +0 -64
  180. package/skills/wix-headless-replatform/scripts/optimize-svg.mjs +0 -31
  181. package/skills/wix-headless-replatform/scripts/post-build-gap.mjs +0 -358
  182. package/skills/wix-headless-replatform/scripts/provision-repeater-cms.mjs +0 -25
  183. package/skills/wix-headless-replatform/scripts/record-gap-decision.mjs +0 -39
  184. package/skills/wix-headless-replatform/scripts/replay-extraction.mjs +0 -107
  185. package/skills/wix-headless-replatform/scripts/resolve-home-page.mjs +0 -96
  186. package/skills/wix-headless-replatform/scripts/site-clone.mjs +0 -658
  187. package/skills/wix-headless-replatform/scripts/validate-font-contract.mjs +0 -29
  188. package/skills/wix-headless-replatform/scripts/verify-interactions.mjs +0 -669
  189. package/skills/wix-headless-replatform/scripts/visual-qa.mjs +0 -370
  190. package/skills/wix-import/SKILL.md +0 -90
  191. package/skills/wix-replatform/.publish-manifest.json +0 -8
  192. package/skills/wix-replatform/CLI.md +0 -162
  193. package/skills/wix-replatform/README.md +0 -52
  194. package/skills/wix-replatform/SKILL.md +0 -238
  195. package/skills/wix-replatform/console/account.css +0 -1
  196. package/skills/wix-replatform/console/app.css +0 -1
  197. package/skills/wix-replatform/console/app.js +0 -117
  198. package/skills/wix-replatform/console/index.html +0 -4
  199. package/skills/wix-replatform/console/json.css +0 -11
  200. package/skills/wix-replatform/lib/agent-adapters/index.js +0 -71
  201. package/skills/wix-replatform/lib/app-page-routing.js +0 -75
  202. package/skills/wix-replatform/lib/artifact-freshness.js +0 -225
  203. package/skills/wix-replatform/lib/blocked-data-requests.js +0 -427
  204. package/skills/wix-replatform/lib/census-reconciliation.js +0 -426
  205. package/skills/wix-replatform/lib/completion-report.js +0 -1580
  206. package/skills/wix-replatform/lib/config-env.js +0 -133
  207. package/skills/wix-replatform/lib/confirmed-pictures.js +0 -212
  208. package/skills/wix-replatform/lib/dependency-readiness.js +0 -423
  209. package/skills/wix-replatform/lib/dependency-recovery.js +0 -21
  210. package/skills/wix-replatform/lib/destination-choice.js +0 -163
  211. package/skills/wix-replatform/lib/destination-handoff.js +0 -62
  212. package/skills/wix-replatform/lib/destination-http.js +0 -81
  213. package/skills/wix-replatform/lib/destination-route.js +0 -98
  214. package/skills/wix-replatform/lib/destination.js +0 -919
  215. package/skills/wix-replatform/lib/discovered-census.js +0 -231
  216. package/skills/wix-replatform/lib/discovered-set-status.js +0 -255
  217. package/skills/wix-replatform/lib/document-url-guard.js +0 -203
  218. package/skills/wix-replatform/lib/entity-qa-attestation.js +0 -339
  219. package/skills/wix-replatform/lib/entity-verification.js +0 -18
  220. package/skills/wix-replatform/lib/execution-capability.js +0 -120
  221. package/skills/wix-replatform/lib/execution-log.js +0 -170
  222. package/skills/wix-replatform/lib/execution-manifest.js +0 -203
  223. package/skills/wix-replatform/lib/execution-state.js +0 -195
  224. package/skills/wix-replatform/lib/expectations-ledger.js +0 -96
  225. package/skills/wix-replatform/lib/generated-plugin-handoff.js +0 -140
  226. package/skills/wix-replatform/lib/import-readiness-contract.js +0 -23
  227. package/skills/wix-replatform/lib/import-recovery.js +0 -1107
  228. package/skills/wix-replatform/lib/imported-redirect-targets.js +0 -608
  229. package/skills/wix-replatform/lib/internal-link-reconciliation.js +0 -166
  230. package/skills/wix-replatform/lib/link-audit.js +0 -173
  231. package/skills/wix-replatform/lib/link-census.js +0 -194
  232. package/skills/wix-replatform/lib/link-plan.js +0 -148
  233. package/skills/wix-replatform/lib/link-verification.js +0 -274
  234. package/skills/wix-replatform/lib/link-write-journal.js +0 -42
  235. package/skills/wix-replatform/lib/local-state.js +0 -1481
  236. package/skills/wix-replatform/lib/member-completion.js +0 -658
  237. package/skills/wix-replatform/lib/member-crosswalk.js +0 -69
  238. package/skills/wix-replatform/lib/member-outcome-registry.js +0 -265
  239. package/skills/wix-replatform/lib/migration-completion.js +0 -311
  240. package/skills/wix-replatform/lib/operator-identity.js +0 -47
  241. package/skills/wix-replatform/lib/orchestration-decisions.js +0 -248
  242. package/skills/wix-replatform/lib/orchestration-preflight.js +0 -525
  243. package/skills/wix-replatform/lib/orchestration-router.js +0 -698
  244. package/skills/wix-replatform/lib/orchestration-state.js +0 -631
  245. package/skills/wix-replatform/lib/order-reference-readiness.js +0 -30
  246. package/skills/wix-replatform/lib/payments-outcome-registry.js +0 -200
  247. package/skills/wix-replatform/lib/plugin-cms-fallback.js +0 -618
  248. package/skills/wix-replatform/lib/preservation-approval-stamp.js +0 -54
  249. package/skills/wix-replatform/lib/product-media-deferral.js +0 -96
  250. package/skills/wix-replatform/lib/progress-log.js +0 -240
  251. package/skills/wix-replatform/lib/progress-log.sh +0 -140
  252. package/skills/wix-replatform/lib/read-back-approval.js +0 -184
  253. package/skills/wix-replatform/lib/read-back-comparison.js +0 -136
  254. package/skills/wix-replatform/lib/read-back-contract.js +0 -243
  255. package/skills/wix-replatform/lib/read-back-extract.js +0 -118
  256. package/skills/wix-replatform/lib/read-back-gate.js +0 -734
  257. package/skills/wix-replatform/lib/read-back-reads.js +0 -94
  258. package/skills/wix-replatform/lib/read-back-state.js +0 -107
  259. package/skills/wix-replatform/lib/read-back-summary.js +0 -81
  260. package/skills/wix-replatform/lib/rerun-conflicts.js +0 -334
  261. package/skills/wix-replatform/lib/run-controller.js +0 -401
  262. package/skills/wix-replatform/lib/seo-outcome-registry.js +0 -45
  263. package/skills/wix-replatform/lib/setup-verification.js +0 -148
  264. package/skills/wix-replatform/lib/source-access.js +0 -231
  265. package/skills/wix-replatform/lib/source-coverage.js +0 -1130
  266. package/skills/wix-replatform/lib/source-secrets.js +0 -277
  267. package/skills/wix-replatform/lib/structured-link-patch.js +0 -59
  268. package/skills/wix-replatform/lib/task-state.js +0 -110
  269. package/skills/wix-replatform/lib/url-preservation-report.js +0 -319
  270. package/skills/wix-replatform/lib/url-preservation-state.js +0 -739
  271. package/skills/wix-replatform/lib/url-redirect-plan.js +0 -728
  272. package/skills/wix-replatform/lib/url-verification.js +0 -315
  273. package/skills/wix-replatform/lib/user-action-effects.js +0 -42
  274. package/skills/wix-replatform/lib/user-actions.js +0 -264
  275. package/skills/wix-replatform/lib/website-handoff.js +0 -1220
  276. package/skills/wix-replatform/lib/wix-client-callers.js +0 -54
  277. package/skills/wix-replatform/lib/wix-dashboard-url.js +0 -35
  278. package/skills/wix-replatform/lib/write-verification-state.js +0 -92
  279. package/skills/wix-replatform/lib/write-verification.js +0 -274
  280. package/skills/wix-replatform/resources/rp-destination/SKILL.md +0 -137
  281. package/skills/wix-replatform/resources/rp-discovery/SKILL.md +0 -357
  282. package/skills/wix-replatform/resources/rp-discovery/scripts/promote-source-coverage.js +0 -47
  283. package/skills/wix-replatform/resources/rp-execute-import/SKILL.md +0 -1369
  284. package/skills/wix-replatform/resources/rp-execute-import/scripts/shipping-estimate-audit.js +0 -70
  285. package/skills/wix-replatform/resources/rp-execute-setup/SKILL.md +0 -482
  286. package/skills/wix-replatform/resources/rp-execute-setup/scripts/execute-setup.js +0 -442
  287. package/skills/wix-replatform/resources/rp-execute-setup/scripts/mint-token.sh +0 -64
  288. package/skills/wix-replatform/resources/rp-execution-policy/SKILL.md +0 -112
  289. package/skills/wix-replatform/resources/rp-execution-policy/lib/coupon-currency-plan-report.js +0 -143
  290. package/skills/wix-replatform/resources/rp-execution-policy/lib/payments-report.js +0 -244
  291. package/skills/wix-replatform/resources/rp-import-codegen/SKILL.md +0 -3158
  292. package/skills/wix-replatform/resources/rp-mapper/SKILL.md +0 -947
  293. package/skills/wix-replatform/resources/rp-mapper/lib/mapping-resolve.js +0 -217
  294. package/skills/wix-replatform/resources/rp-mapper/lib/structure-bridge-planning.js +0 -303
  295. package/skills/wix-replatform/resources/rp-mapper/scripts/coverage-reconcile.js +0 -88
  296. package/skills/wix-replatform/resources/rp-mapper/scripts/resolve-mapping.js +0 -148
  297. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +0 -378
  298. package/skills/wix-replatform/resources/rp-preflight/SKILL.md +0 -40
  299. package/skills/wix-replatform/resources/rp-project-intake/SKILL.md +0 -55
  300. package/skills/wix-replatform/resources/rp-quick-runtime/SKILL.md +0 -60
  301. package/skills/wix-replatform/resources/rp-quick-runtime/lib/import-progress.js +0 -89
  302. package/skills/wix-replatform/resources/rp-quick-runtime/lib/limit-recovery.js +0 -36
  303. package/skills/wix-replatform/resources/rp-quick-shopify/SKILL.md +0 -123
  304. package/skills/wix-replatform/resources/rp-quick-shopify/quick-mode.json +0 -124
  305. package/skills/wix-replatform/resources/rp-quick-shopify/scripts/quick-mode.js +0 -522
  306. package/skills/wix-replatform/resources/rp-quick-woocommerce/SKILL.md +0 -56
  307. package/skills/wix-replatform/resources/rp-quick-woocommerce/quick-mode.json +0 -91
  308. package/skills/wix-replatform/resources/rp-quick-woocommerce/scripts/quick-mode.js +0 -255
  309. package/skills/wix-replatform/resources/rp-setup-discovery/SKILL.md +0 -253
  310. package/skills/wix-replatform/resources/rp-setup-discovery/scripts/quick-setup-plan.js +0 -44
  311. package/skills/wix-replatform/resources/rp-source-csv/SKILL.md +0 -481
  312. package/skills/wix-replatform/resources/rp-source-csv/lib/canonical-record.js +0 -136
  313. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fileset.js +0 -0
  314. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fingerprint.js +0 -310
  315. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-layout.js +0 -1081
  316. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-parse.js +0 -618
  317. package/skills/wix-replatform/resources/rp-source-csv/scripts/csv-discovery.js +0 -969
  318. package/skills/wix-replatform/resources/rp-source-csv/source-schema.example.json +0 -196
  319. package/skills/wix-replatform/resources/rp-source-csv/vendors/bigcommerce.json +0 -66
  320. package/skills/wix-replatform/resources/rp-source-csv/vendors/magento.json +0 -60
  321. package/skills/wix-replatform/resources/rp-source-csv/vendors/shopify.json +0 -95
  322. package/skills/wix-replatform/resources/rp-source-csv/vendors/woocommerce.json +0 -82
  323. package/skills/wix-replatform/resources/rp-source-inputs/SKILL.md +0 -66
  324. package/skills/wix-replatform/resources/rp-source-sfcc/SKILL.md +0 -153
  325. package/skills/wix-replatform/resources/rp-source-shopify/SKILL.md +0 -394
  326. package/skills/wix-replatform/resources/rp-source-shopify/lib/discovery-reads.js +0 -200
  327. package/skills/wix-replatform/resources/rp-source-shopify/lib/import-findings.js +0 -34
  328. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-bulk-sqlite-worker.js +0 -44
  329. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-bulk.js +0 -1470
  330. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-cli.js +0 -446
  331. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-gift-cards.js +0 -474
  332. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-protected-fields.js +0 -879
  333. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-session.js +0 -426
  334. package/skills/wix-replatform/resources/rp-source-shopify/queries/articles.graphql +0 -24
  335. package/skills/wix-replatform/resources/rp-source-shopify/queries/blogs.graphql +0 -18
  336. package/skills/wix-replatform/resources/rp-source-shopify/queries/collections.graphql +0 -40
  337. package/skills/wix-replatform/resources/rp-source-shopify/queries/customers.graphql +0 -76
  338. package/skills/wix-replatform/resources/rp-source-shopify/queries/delivery-profiles.graphql +0 -51
  339. package/skills/wix-replatform/resources/rp-source-shopify/queries/discounts.graphql +0 -35
  340. package/skills/wix-replatform/resources/rp-source-shopify/queries/files.graphql +0 -20
  341. package/skills/wix-replatform/resources/rp-source-shopify/queries/gift-cards.graphql +0 -18
  342. package/skills/wix-replatform/resources/rp-source-shopify/queries/inventory.graphql +0 -31
  343. package/skills/wix-replatform/resources/rp-source-shopify/queries/locations.graphql +0 -21
  344. package/skills/wix-replatform/resources/rp-source-shopify/queries/menus.graphql +0 -21
  345. package/skills/wix-replatform/resources/rp-source-shopify/queries/metaobjects.graphql +0 -30
  346. package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-core.graphql +0 -150
  347. package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-fulfillments.graphql +0 -36
  348. package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-refunds.graphql +0 -48
  349. package/skills/wix-replatform/resources/rp-source-shopify/queries/pages.graphql +0 -20
  350. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-address.graphql +0 -8
  351. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-email.graphql +0 -6
  352. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-name.graphql +0 -8
  353. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-phone.graphql +0 -8
  354. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-address.graphql +0 -12
  355. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-email.graphql +0 -6
  356. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-name.graphql +0 -13
  357. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-phone.graphql +0 -13
  358. package/skills/wix-replatform/resources/rp-source-shopify/queries/products.graphql +0 -73
  359. package/skills/wix-replatform/resources/rp-source-shopify/queries/url-redirects.graphql +0 -13
  360. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-discovery.js +0 -693
  361. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-extract.js +0 -283
  362. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-gift-card-remedy.js +0 -191
  363. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-session-check.js +0 -115
  364. package/skills/wix-replatform/resources/rp-source-shopify/source-schema.example.json +0 -201
  365. package/skills/wix-replatform/resources/rp-source-wordpress/PLUGIN-READ-PLANS.md +0 -146
  366. package/skills/wix-replatform/resources/rp-source-wordpress/SKILL.md +0 -970
  367. package/skills/wix-replatform/resources/rp-source-wordpress/lib/blocked-data-handlers.js +0 -73
  368. package/skills/wix-replatform/resources/rp-source-wordpress/lib/checkout-field-csv-parser.js +0 -115
  369. package/skills/wix-replatform/resources/rp-source-wordpress/lib/checkout-field-csv-parser.test-fixture.js +0 -91
  370. package/skills/wix-replatform/resources/rp-source-wordpress/lib/coupon-discovery.js +0 -440
  371. package/skills/wix-replatform/resources/rp-source-wordpress/lib/currency-gate.js +0 -125
  372. package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-source-keys.js +0 -252
  373. package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-source-keys.json +0 -183
  374. package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-summary.mjs +0 -333
  375. package/skills/wix-replatform/resources/rp-source-wordpress/lib/invoice-discovery.js +0 -426
  376. package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-disposition.js +0 -400
  377. package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-entity-read-plan.js +0 -633
  378. package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-knowledge.js +0 -1127
  379. package/skills/wix-replatform/resources/rp-source-wordpress/lib/refund-corroboration.js +0 -194
  380. package/skills/wix-replatform/resources/rp-source-wordpress/lib/refund-corroboration.json +0 -100
  381. package/skills/wix-replatform/resources/rp-source-wordpress/lib/sampled-ids-batch.js +0 -157
  382. package/skills/wix-replatform/resources/rp-source-wordpress/lib/secret-value-guard.js +0 -234
  383. package/skills/wix-replatform/resources/rp-source-wordpress/lib/store-currency.js +0 -101
  384. package/skills/wix-replatform/resources/rp-source-wordpress/lib/structure-bridge-reader.js +0 -755
  385. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wix-wp-plugin-v2-client.js +0 -1074
  386. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wix-wp-plugin-v2-client.test-fixture.js +0 -149
  387. package/skills/wix-replatform/resources/rp-source-wordpress/lib/woo-inventory.js +0 -25
  388. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-http.js +0 -444
  389. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-image-url.js +0 -186
  390. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-plugin-detect.js +0 -1422
  391. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-redirect-sources.js +0 -343
  392. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-route-classifier.js +0 -680
  393. package/skills/wix-replatform/resources/rp-source-wordpress/lib/yoast-product-seo-evidence.js +0 -272
  394. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/README.md +0 -373
  395. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/advanced-custom-fields.json +0 -101
  396. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/back-in-stock-notifier-for-woocommerce.json +0 -81
  397. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/capabilities-pending-decision.json +0 -128
  398. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/cms-fallback-eligible.json +0 -18
  399. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/contact-form-7.json +0 -104
  400. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/facebook-for-woocommerce.json +0 -44
  401. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/fingerprint-aliases.json +0 -49
  402. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/free-gifts-for-woocommerce.json +0 -94
  403. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/index.json +0 -863
  404. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/mailpoet.json +0 -52
  405. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/membership-for-woocommerce.json +0 -161
  406. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/mwb-bookings-for-woocommerce.json +0 -180
  407. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/no-migration-needed.json +0 -286
  408. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/pricing-deals-for-woocommerce.json +0 -79
  409. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/product-extras-for-woocommerce.json +0 -120
  410. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/pw-woocommerce-gift-cards.json +0 -128
  411. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/requires-development.json +0 -88
  412. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/seo-by-rank-math.json +0 -80
  413. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/seriously-simple-podcasting.json +0 -46
  414. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/strong-testimonials.json +0 -55
  415. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/subscriptions-for-woocommerce.json +0 -99
  416. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/tablepress.json +0 -55
  417. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/the-events-calendar.json +0 -160
  418. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/ti-woocommerce-wishlist.json +0 -81
  419. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-checkout-field-editor-pro.json +0 -60
  420. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-discount-rules.json +0 -74
  421. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-product-bundle.json +0 -75
  422. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-gift-cards.json +0 -60
  423. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-other-payment-gateway.json +0 -44
  424. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-pdf-invoices-packing-slips.json +0 -57
  425. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-product-addon.json +0 -141
  426. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-progressive-discounts.json +0 -54
  427. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wordpress-seo.json +0 -158
  428. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wpc-composite-products.json +0 -97
  429. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wpforms-lite.json +0 -86
  430. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/capture-store-settings.js +0 -90
  431. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/plugin-knowledge-validate.js +0 -51
  432. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/plugin-knowledge.js +0 -103
  433. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-discovery.js +0 -2409
  434. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-plugin-inventory.js +0 -273
  435. package/skills/wix-replatform/resources/rp-source-wordpress/secret-value-patterns.v1.json +0 -11
  436. package/skills/wix-replatform/resources/rp-source-wordpress/source-schema.example.json +0 -71
  437. package/skills/wix-replatform/resources/rp-source-wordpress/sub-parts.json +0 -13
  438. package/skills/wix-replatform/resources/rp-target-wix/SKILL.md +0 -1046
  439. package/skills/wix-replatform/resources/rp-target-wix/app-page-routing-capabilities.json +0 -36
  440. package/skills/wix-replatform/resources/rp-target-wix/domains/README.md +0 -57
  441. package/skills/wix-replatform/resources/rp-target-wix/domains/SERVICE-PLUGINS.md +0 -322
  442. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/docs-survey.json +0 -70
  443. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/domain.json +0 -29
  444. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/category.json +0 -71
  445. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/comment.json +0 -83
  446. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/post.json +0 -95
  447. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/tag.json +0 -66
  448. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/docs-survey.json +0 -332
  449. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/domain.json +0 -75
  450. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/booking.json +0 -181
  451. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/service-add-on.json +0 -130
  452. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/service.json +0 -180
  453. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/docs-survey.json +0 -161
  454. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/domain.json +0 -25
  455. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/collection.json +0 -67
  456. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/data-item.json +0 -75
  457. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/reference.json +0 -41
  458. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/docs-survey.json +0 -204
  459. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/domain.json +0 -27
  460. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/contact.json +0 -275
  461. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/email-subscription.json +0 -105
  462. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/label.json +0 -77
  463. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/docs-survey.json +0 -297
  464. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/domain.json +0 -44
  465. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/delivery-profile.json +0 -171
  466. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/discount-rule.json +0 -182
  467. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-applied-discount.json +0 -129
  468. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-invoice-document.json +0 -192
  469. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item-options.json +0 -123
  470. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item.json +0 -85
  471. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-merchant-note.json +0 -112
  472. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-payment.json +0 -191
  473. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-refund.json +0 -164
  474. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order.json +0 -462
  475. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/pickup-location.json +0 -122
  476. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/shipping-option.json +0 -98
  477. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/wishlist-item.json +0 -86
  478. package/skills/wix-replatform/resources/rp-target-wix/domains/events/docs-survey.json +0 -128
  479. package/skills/wix-replatform/resources/rp-target-wix/domains/events/domain.json +0 -38
  480. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/category.json +0 -73
  481. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/event.json +0 -107
  482. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/registration-form.json +0 -89
  483. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/rsvp.json +0 -118
  484. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/ticket-definition.json +0 -93
  485. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/docs-survey.json +0 -86
  486. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/domain.json +0 -56
  487. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/entities/form-submission.json +0 -121
  488. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/entities/form.json +0 -134
  489. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/docs-survey.json +0 -41
  490. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/domain.json +0 -50
  491. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/entities/gift-card-product.json +0 -87
  492. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/entities/gift-card.json +0 -130
  493. package/skills/wix-replatform/resources/rp-target-wix/domains/index.json +0 -1418
  494. package/skills/wix-replatform/resources/rp-target-wix/domains/media/docs-survey.json +0 -41
  495. package/skills/wix-replatform/resources/rp-target-wix/domains/media/domain.json +0 -24
  496. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-file.json +0 -75
  497. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-folder.json +0 -71
  498. package/skills/wix-replatform/resources/rp-target-wix/domains/members/docs-survey.json +0 -119
  499. package/skills/wix-replatform/resources/rp-target-wix/domains/members/domain.json +0 -23
  500. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/badge.json +0 -71
  501. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/custom-field.json +0 -82
  502. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member-about.json +0 -77
  503. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member.json +0 -205
  504. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/docs-survey.json +0 -41
  505. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/domain.json +0 -46
  506. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/entities/plan-order.json +0 -137
  507. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/entities/plan.json +0 -133
  508. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/docs-survey.json +0 -7
  509. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/domain.json +0 -36
  510. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/amazon-shop-connect.json +0 -71
  511. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/ebay-shop-connect.json +0 -67
  512. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/google-youtube-connect.json +0 -72
  513. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/meta-catalog-connect.json +0 -74
  514. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/pinterest-catalog-connect.json +0 -69
  515. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/tiktok-catalog-connect.json +0 -61
  516. package/skills/wix-replatform/resources/rp-target-wix/domains/schema.json +0 -111
  517. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/docs-survey.json +0 -109
  518. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/domain.json +0 -73
  519. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/item-seo-tags.json +0 -148
  520. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/seo-pattern.json +0 -91
  521. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/site-seo-tags.json +0 -79
  522. package/skills/wix-replatform/resources/rp-target-wix/domains/site/docs-survey.json +0 -32
  523. package/skills/wix-replatform/resources/rp-target-wix/domains/site/domain.json +0 -49
  524. package/skills/wix-replatform/resources/rp-target-wix/domains/site/entities/business-contact.json +0 -103
  525. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/docs-survey.json +0 -203
  526. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/domain.json +0 -42
  527. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/back-in-stock-request.json +0 -119
  528. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/brand.json +0 -111
  529. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/category.json +0 -81
  530. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/coupon.json +0 -241
  531. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/inventory-item.json +0 -118
  532. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-customization.json +0 -111
  533. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-tag.json +0 -79
  534. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product.json +0 -221
  535. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/promotion.json +0 -84
  536. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/review.json +0 -178
  537. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/subscription-product.json +0 -87
  538. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/docs-survey.json +0 -106
  539. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/domain.json +0 -64
  540. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/manual-tax-mapping.json +0 -119
  541. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-group.json +0 -94
  542. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-region.json +0 -113
  543. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-settings.json +0 -65
  544. package/skills/wix-replatform/resources/rp-target-wix/lib/audit-summary.js +0 -64
  545. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-author-attribution.js +0 -165
  546. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-client.js +0 -60
  547. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-duplicates.js +0 -201
  548. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-ledger.js +0 -306
  549. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-report.js +0 -229
  550. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-stage.js +0 -55
  551. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build.js +0 -715
  552. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-media.js +0 -567
  553. package/skills/wix-replatform/resources/rp-target-wix/lib/bulk-results.js +0 -73
  554. package/skills/wix-replatform/resources/rp-target-wix/lib/contact-extended-fields.js +0 -194
  555. package/skills/wix-replatform/resources/rp-target-wix/lib/contact-import.js +0 -133
  556. package/skills/wix-replatform/resources/rp-target-wix/lib/contract-ledger.js +0 -150
  557. package/skills/wix-replatform/resources/rp-target-wix/lib/coupon-redemption-drift.js +0 -491
  558. package/skills/wix-replatform/resources/rp-target-wix/lib/customer-member.js +0 -104
  559. package/skills/wix-replatform/resources/rp-target-wix/lib/data-extension-schema.js +0 -673
  560. package/skills/wix-replatform/resources/rp-target-wix/lib/domain-knowledge.js +0 -835
  561. package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-balance-reconciliation.js +0 -119
  562. package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-build.js +0 -566
  563. package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-redemption-build.js +0 -249
  564. package/skills/wix-replatform/resources/rp-target-wix/lib/ndjson.js +0 -260
  565. package/skills/wix-replatform/resources/rp-target-wix/lib/order-applied-discount-build.js +0 -63
  566. package/skills/wix-replatform/resources/rp-target-wix/lib/order-buyer.js +0 -187
  567. package/skills/wix-replatform/resources/rp-target-wix/lib/order-channel-build.js +0 -64
  568. package/skills/wix-replatform/resources/rp-target-wix/lib/order-history.js +0 -1027
  569. package/skills/wix-replatform/resources/rp-target-wix/lib/order-invoice-contract.js +0 -90
  570. package/skills/wix-replatform/resources/rp-target-wix/lib/order-payment-mapping.js +0 -420
  571. package/skills/wix-replatform/resources/rp-target-wix/lib/pricing-plan-definition.js +0 -177
  572. package/skills/wix-replatform/resources/rp-target-wix/lib/product-import.js +0 -151
  573. package/skills/wix-replatform/resources/rp-target-wix/lib/product-seo.js +0 -723
  574. package/skills/wix-replatform/resources/rp-target-wix/lib/seo-redirects.js +0 -353
  575. package/skills/wix-replatform/resources/rp-target-wix/lib/shipping-build.js +0 -1437
  576. package/skills/wix-replatform/resources/rp-target-wix/lib/shipping-option-stage.js +0 -354
  577. package/skills/wix-replatform/resources/rp-target-wix/lib/store-config-build.js +0 -134
  578. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-category-attach.js +0 -221
  579. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-inventory.js +0 -248
  580. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-verification.js +0 -321
  581. package/skills/wix-replatform/resources/rp-target-wix/lib/tax-build.js +0 -231
  582. package/skills/wix-replatform/resources/rp-target-wix/lib/url-mapper-transport.js +0 -28
  583. package/skills/wix-replatform/resources/rp-target-wix/lib/value-utils.js +0 -14
  584. package/skills/wix-replatform/resources/rp-target-wix/lib/variant-correlation.js +0 -34
  585. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-build.js +0 -388
  586. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-target-spec.js +0 -255
  587. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +0 -6041
  588. package/skills/wix-replatform/resources/rp-target-wix/lib/write-verification.js +0 -3
  589. package/skills/wix-replatform/resources/rp-target-wix/scripts/docs-survey-sync.js +0 -150
  590. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge-validate.js +0 -69
  591. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge.js +0 -100
  592. package/skills/wix-replatform/resources/rp-target-wix/scripts/verify-stores.js +0 -112
  593. package/skills/wix-replatform/resources/rp-telemetry/SKILL.md +0 -484
  594. package/skills/wix-replatform/resources/rp-telemetry/lib/bi-sink.js +0 -318
  595. package/skills/wix-replatform/resources/rp-telemetry/lib/telemetry-recorder.js +0 -2831
  596. package/skills/wix-replatform/resources/rp-telemetry/lib/transcript-digest.js +0 -318
  597. package/skills/wix-replatform/resources/rp-telemetry/scripts/meter-from-audit.js +0 -83
  598. package/skills/wix-replatform/resources/rp-telemetry/scripts/rp-telemetry.js +0 -243
  599. package/skills/wix-replatform/resources/rp-website-continuation/SKILL.md +0 -94
  600. package/skills/wix-replatform/scripts/artifact-freshness.js +0 -76
  601. package/skills/wix-replatform/scripts/census-reconciliation.js +0 -25
  602. package/skills/wix-replatform/scripts/cms-fallback.js +0 -89
  603. package/skills/wix-replatform/scripts/discovered-census.js +0 -26
  604. package/skills/wix-replatform/scripts/discovered-set-status.js +0 -33
  605. package/skills/wix-replatform/scripts/entity-qa-attestation.js +0 -130
  606. package/skills/wix-replatform/scripts/execution-health-check.js +0 -415
  607. package/skills/wix-replatform/scripts/execution-manifest-validate.js +0 -43
  608. package/skills/wix-replatform/scripts/execution-state-prepare.js +0 -128
  609. package/skills/wix-replatform/scripts/expectations-ledger.js +0 -44
  610. package/skills/wix-replatform/scripts/import-contract-verify.js +0 -183
  611. package/skills/wix-replatform/scripts/internal-link-audit.js +0 -90
  612. package/skills/wix-replatform/scripts/item-seo-tags-verify.js +0 -205
  613. package/skills/wix-replatform/scripts/migration-completion.js +0 -76
  614. package/skills/wix-replatform/scripts/orchestration-preflight.js +0 -67
  615. package/skills/wix-replatform/scripts/orchestration-route.js +0 -77
  616. package/skills/wix-replatform/scripts/orchestration-state.js +0 -381
  617. package/skills/wix-replatform/scripts/read-back-gate.js +0 -175
  618. package/skills/wix-replatform/scripts/replatform-console.js +0 -146
  619. package/skills/wix-replatform/scripts/replatform.js +0 -436
  620. package/skills/wix-replatform/scripts/source-secrets.js +0 -77
  621. package/skills/wix-replatform/scripts/url-redirects.js +0 -286
  622. package/skills/wix-replatform/scripts/user-action.js +0 -58
  623. package/skills/wix-replatform/scripts/website-handoff-generate.js +0 -64
  624. package/skills/wix-replatform/scripts/wix-dashboard-url.js +0 -54
  625. package/skills/wix-replatform/scripts/wix-destination.js +0 -143
  626. package/skills/wix-replatform/scripts/wix-headless-scaffold.js +0 -762
  627. package/skills/wix-vibe-headless/SKILL.md +0 -183
  628. package/skills/wix-vibe-headless/install/deploy.cjs +0 -221
  629. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +0 -35
  630. package/skills/wix-vibe-headless/platforms/README.md +0 -26
  631. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +0 -127
  632. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +0 -121
  633. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +0 -87
  634. package/skills/wix-vibe-headless/platforms/base44.md +0 -148
  635. package/skills/wix-vibe-headless/platforms/generic.md +0 -132
  636. package/skills/wix-vibe-headless/references/_shared/nav/nav.tanstack.js +0 -30
  637. package/skills/wix-vibe-headless/references/_shared/routing.md +0 -86
  638. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +0 -270
  639. package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +0 -43
  640. package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +0 -25
  641. package/skills/wix-vibe-headless/references/blog/app/components/PostGrid.jsx +0 -15
  642. package/skills/wix-vibe-headless/references/blog/app/context/TaxonomyContext.jsx +0 -35
  643. package/skills/wix-vibe-headless/references/blog/app/hooks/usePostDetail.js +0 -38
  644. package/skills/wix-vibe-headless/references/blog/app/pages/Blog.jsx +0 -40
  645. package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +0 -54
  646. package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +0 -65
  647. package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +0 -50
  648. package/skills/wix-vibe-headless/references/blog/app/rest/wix-blog.js +0 -217
  649. package/skills/wix-vibe-headless/references/blog/seed/SEED.md +0 -99
  650. package/skills/wix-vibe-headless/references/blog/seed/seed-blog.cjs +0 -269
  651. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +0 -342
  652. package/skills/wix-vibe-headless/references/bookings/app/components/BookingForm.jsx +0 -65
  653. package/skills/wix-vibe-headless/references/bookings/app/components/RentalDurationPicker.jsx +0 -67
  654. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +0 -47
  655. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceGrid.jsx +0 -13
  656. package/skills/wix-vibe-headless/references/bookings/app/components/SlotPicker.jsx +0 -126
  657. package/skills/wix-vibe-headless/references/bookings/app/hooks/useRentalDuration.js +0 -128
  658. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +0 -110
  659. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServices.js +0 -58
  660. package/skills/wix-vibe-headless/references/bookings/app/lib/serviceFacts.js +0 -95
  661. package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +0 -94
  662. package/skills/wix-vibe-headless/references/bookings/app/pages/Services.jsx +0 -89
  663. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +0 -148
  664. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-rentals.js +0 -250
  665. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-services.js +0 -300
  666. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +0 -154
  667. package/skills/wix-vibe-headless/references/bookings/seed/seed-bookings.cjs +0 -333
  668. package/skills/wix-vibe-headless/references/bookings/seed/seed-rentals.cjs +0 -267
  669. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +0 -178
  670. package/skills/wix-vibe-headless/references/cms/app/collection.config.js +0 -31
  671. package/skills/wix-vibe-headless/references/cms/app/lib/wixImage.js +0 -18
  672. package/skills/wix-vibe-headless/references/cms/app/rest/wix-cms.js +0 -231
  673. package/skills/wix-vibe-headless/references/cms/seed/SEED.md +0 -145
  674. package/skills/wix-vibe-headless/references/donations/INSTRUCTIONS.md +0 -88
  675. package/skills/wix-vibe-headless/references/donations/app/rest/wix-donations.js +0 -112
  676. package/skills/wix-vibe-headless/references/donations/seed/SEED.md +0 -11
  677. package/skills/wix-vibe-headless/references/donations/tests/donations.test.mjs +0 -258
  678. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +0 -267
  679. package/skills/wix-vibe-headless/references/events/app/components/CategoryFilter.jsx +0 -23
  680. package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +0 -43
  681. package/skills/wix-vibe-headless/references/events/app/components/EventGrid.jsx +0 -13
  682. package/skills/wix-vibe-headless/references/events/app/components/EventRegistration.jsx +0 -29
  683. package/skills/wix-vibe-headless/references/events/app/components/RsvpForm.jsx +0 -57
  684. package/skills/wix-vibe-headless/references/events/app/components/TicketPicker.jsx +0 -78
  685. package/skills/wix-vibe-headless/references/events/app/hooks/useEventDetail.js +0 -27
  686. package/skills/wix-vibe-headless/references/events/app/hooks/useEventsList.js +0 -54
  687. package/skills/wix-vibe-headless/references/events/app/hooks/useRsvpForm.js +0 -40
  688. package/skills/wix-vibe-headless/references/events/app/hooks/useTicketing.js +0 -81
  689. package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +0 -48
  690. package/skills/wix-vibe-headless/references/events/app/pages/Events.jsx +0 -36
  691. package/skills/wix-vibe-headless/references/events/app/rest/wix-events-browse.js +0 -136
  692. package/skills/wix-vibe-headless/references/events/app/rest/wix-events-registration.js +0 -187
  693. package/skills/wix-vibe-headless/references/events/seed/SEED.md +0 -103
  694. package/skills/wix-vibe-headless/references/events/seed/seed-events.cjs +0 -251
  695. package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +0 -487
  696. package/skills/wix-vibe-headless/references/forms/app/hooks/useWixForm.js +0 -425
  697. package/skills/wix-vibe-headless/references/forms/app/lib/wix-form-schema-utils.js +0 -187
  698. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms-submissions.js +0 -238
  699. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms.js +0 -108
  700. package/skills/wix-vibe-headless/references/forms/seed/SEED.md +0 -1836
  701. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +0 -328
  702. package/skills/wix-vibe-headless/references/members/app/components/LoginForm.jsx +0 -101
  703. package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +0 -33
  704. package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +0 -21
  705. package/skills/wix-vibe-headless/references/members/app/components/SocialButtons.jsx +0 -29
  706. package/skills/wix-vibe-headless/references/members/app/context/MemberContext.jsx +0 -54
  707. package/skills/wix-vibe-headless/references/members/app/hooks/useLoginForm.js +0 -77
  708. package/skills/wix-vibe-headless/references/members/app/pages/Account.jsx +0 -36
  709. package/skills/wix-vibe-headless/references/members/app/pages/Callback.jsx +0 -32
  710. package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +0 -35
  711. package/skills/wix-vibe-headless/references/members/app/rest/wix-members-auth.js +0 -390
  712. package/skills/wix-vibe-headless/references/members/install/Register.jsx +0 -22
  713. package/skills/wix-vibe-headless/references/members/seed/SEED.md +0 -21
  714. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +0 -270
  715. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +0 -31
  716. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionGrid.jsx +0 -15
  717. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +0 -39
  718. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectGrid.jsx +0 -15
  719. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +0 -29
  720. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useCollectionProjects.js +0 -35
  721. package/skills/wix-vibe-headless/references/portfolio/app/hooks/usePortfolioGallery.js +0 -27
  722. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useProjectDetail.js +0 -25
  723. package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +0 -39
  724. package/skills/wix-vibe-headless/references/portfolio/app/pages/Portfolio.jsx +0 -27
  725. package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +0 -60
  726. package/skills/wix-vibe-headless/references/portfolio/app/rest/wix-portfolio.js +0 -223
  727. package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +0 -90
  728. package/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.cjs +0 -236
  729. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +0 -280
  730. package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +0 -35
  731. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +0 -48
  732. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanGrid.jsx +0 -16
  733. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanPrice.jsx +0 -35
  734. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/useMyPlans.js +0 -25
  735. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlanDetail.js +0 -28
  736. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlans.js +0 -30
  737. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/MyPlans.jsx +0 -30
  738. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +0 -53
  739. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/Plans.jsx +0 -28
  740. package/skills/wix-vibe-headless/references/pricing-plans/app/rest/wix-pricing-plans.js +0 -157
  741. package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +0 -82
  742. package/skills/wix-vibe-headless/references/pricing-plans/seed/seed-pricing-plans.cjs +0 -251
  743. package/skills/wix-vibe-headless/references/rentals/INSTRUCTIONS.md +0 -13
  744. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +0 -290
  745. package/skills/wix-vibe-headless/references/restaurants/app/components/ItemDialog.jsx +0 -81
  746. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuItemCard.jsx +0 -71
  747. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuList.jsx +0 -43
  748. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartButton.jsx +0 -21
  749. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +0 -72
  750. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +0 -66
  751. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useItemOrder.js +0 -32
  752. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useReservation.js +0 -73
  753. package/skills/wix-vibe-headless/references/restaurants/app/pages/Menu.jsx +0 -28
  754. package/skills/wix-vibe-headless/references/restaurants/app/pages/Reservations.jsx +0 -102
  755. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-menu.js +0 -224
  756. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +0 -218
  757. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-reservations.js +0 -107
  758. package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +0 -176
  759. package/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.cjs +0 -452
  760. package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +0 -56
  761. package/skills/wix-vibe-headless/references/shared/app/lib/nav.js +0 -9
  762. package/skills/wix-vibe-headless/references/shared/app/rest/wix-client.js +0 -185
  763. package/skills/wix-vibe-headless/references/shared/app/rest/wix-config.js +0 -8
  764. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +0 -471
  765. package/skills/wix-vibe-headless/references/storefront/app/components/CartButton.jsx +0 -20
  766. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +0 -167
  767. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +0 -83
  768. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductCard.js +0 -104
  769. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +0 -163
  770. package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +0 -83
  771. package/skills/wix-vibe-headless/references/storefront/app/hooks/useVariantOptions.js +0 -76
  772. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +0 -64
  773. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +0 -176
  774. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +0 -218
  775. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +0 -174
  776. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.cjs +0 -546
@@ -1,1074 +0,0 @@
1
- 'use strict';
2
-
3
- // Client for wix-wp-plugin-v2 -- the ONLY bridge-plugin-style mechanism this
4
- // skill uses for data with no REST route at all (db-only, or admin-page-only with an
5
- // underlying table). There is no per-capability fixed adapter any more: any db-only
6
- // entity's fulfillment can point at this SAME handler with a different `table`, because
7
- // wix-wp-plugin-v2 itself has no per-capability code -- see plugins/wix-wp-plugin-v2/README.md.
8
- //
9
- // Two capabilities, matching the plugin's own two routes:
10
- // - discoverStructure(): schema only (columns, types, key hints). Safe to call before a
11
- // human has decided anything about a table -- no row data leaves the site.
12
- // - queryStructure(): real row data, via one bounded, parameterized SELECT (select
13
- // columns/aggregates, optional where/groupBy, required orderBy, cursor pagination).
14
- // Pulling real data through this for a specific entity is a per-entity decision, not
15
- // implied by schema-discoverability -- e.g. gift-card-activity's balance/redemption
16
- // ledger still needs its own masking/correlation call even though its
17
- // schema is freely discoverable.
18
-
19
- const { createHash, createHmac, randomUUID, timingSafeEqual } = require('node:crypto');
20
-
21
- const SHARED_CORE_TABLES_REQUIRING_WHERE = new Set(['posts', 'terms', 'term_taxonomy', 'term_relationships', 'comments']);
22
- const MAX_IN_VALUES = 100;
23
- const MAX_WHERE_CONDITIONS = 20;
24
- const HANDLER_VERSION = '1.3.0'; // 1.3.0: signed migration-key transport plus strict response-envelope validation.
25
-
26
- function bodyOf(response) {
27
- return response && response.data !== undefined ? response.data : response;
28
- }
29
-
30
- function assertColumn(column, table) {
31
- if (!column || typeof column.name !== 'string' || column.name.length === 0) {
32
- throw new Error(`table ${table}: column name is required`);
33
- }
34
- if (typeof column.type !== 'string' || column.type.length === 0) {
35
- throw new Error(`table ${table}: column ${column.name} is missing a type`);
36
- }
37
- if (typeof column.nullable !== 'boolean') {
38
- throw new Error(`table ${table}: column ${column.name} is missing nullable`);
39
- }
40
- if (column.key !== null && !['primary', 'unique', 'index'].includes(column.key)) {
41
- throw new Error(`table ${table}: column ${column.name} has an invalid key hint ${JSON.stringify(column.key)}`);
42
- }
43
- }
44
-
45
- const EAV_TIERS = ['key-discovery', 'key-scoped'];
46
-
47
- /**
48
- * `redactionMetadata`, required on every response and validated against the
49
- * schema's actual contract: a NON-NEGATIVE INTEGER count and an array of STRINGS.
50
- *
51
- * The loose version accepted `-1.5` and `[7]`, which was not merely untidy. Those values flow
52
- * straight into `sourceReadCounts()` and on to rp-telemetry, whose validator correctly rejects
53
- * them -- so a malformed count silently discarded the whole accumulated telemetry batch, far
54
- * from the response that caused it. Validate at the boundary, where the error can still name
55
- * the table.
56
- */
57
- function assertRedactionMetadata(redactionMetadata, table) {
58
- if (!redactionMetadata || typeof redactionMetadata !== 'object' || Array.isArray(redactionMetadata)) {
59
- throw new Error(
60
- `table ${table}: response is missing redactionMetadata, which is required on every `
61
- + 'query-structure response. The source site is running a wix-wp-plugin-v2 older than 0.4.0, which has no '
62
- + 'secret-value guard -- upgrade the plugin rather than treating this as an empty redaction set.',
63
- );
64
- }
65
- const { redactedValueCount, redactedColumns } = redactionMetadata;
66
- if (!Number.isInteger(redactedValueCount) || redactedValueCount < 0) {
67
- throw new Error(`table ${table}: redactionMetadata.redactedValueCount must be a non-negative integer (got ${JSON.stringify(redactedValueCount)})`);
68
- }
69
- if (!Array.isArray(redactedColumns) || redactedColumns.some((c) => typeof c !== 'string')) {
70
- throw new Error(`table ${table}: redactionMetadata.redactedColumns must be an array of column names`);
71
- }
72
- if (redactedValueCount > 0 && redactedColumns.length === 0) {
73
- throw new Error(`table ${table}: redactionMetadata reports ${redactedValueCount} redaction(s) but names no column -- a count with no column is not actionable`);
74
- }
75
- return { redactedValueCount, redactedColumns: [...redactedColumns] };
76
- }
77
-
78
- /** A {keyColumn, valueColumn} pair, as reported by either route. */
79
- function assertPairShape(pair, table, where) {
80
- if (!pair || typeof pair.keyColumn !== 'string' || typeof pair.valueColumn !== 'string') {
81
- throw new Error(`table ${table}: ${where} must carry string keyColumn and valueColumn`);
82
- }
83
- return { keyColumn: pair.keyColumn, valueColumn: pair.valueColumn };
84
- }
85
-
86
- /**
87
- * discover-structure's `eavPair`. Absent for an ordinary table; when present it names the
88
- * column a query must pin. `additionalPairs` appears only for the rare schema carrying more
89
- * than one recognized pair -- and it is propagated rather than dropped, because every one of
90
- * those value columns is independently guarded and a caller that saw only the first would
91
- * build a request the plugin refuses.
92
- */
93
- function assertEavPair(eavPair, table) {
94
- if (eavPair === undefined || eavPair === null) return null;
95
- const pair = assertPairShape(eavPair, table, 'eavPair');
96
- if (eavPair.additionalPairs !== undefined) {
97
- if (!Array.isArray(eavPair.additionalPairs)) throw new Error(`table ${table}: eavPair.additionalPairs must be an array`);
98
- pair.additionalPairs = eavPair.additionalPairs.map((p) => assertPairShape(p, table, 'eavPair.additionalPairs[]'));
99
- }
100
- return pair;
101
- }
102
-
103
- /**
104
- * query-structure's `eavAccess`. Absent for a table with no key/value pair; present with a
105
- * tier and the key names the request pinned otherwise. Validated rather than passed through
106
- * so a caller can branch on `tier` without re-checking the shape.
107
- */
108
- function assertAccessPair(pair, table, where) {
109
- const shape = assertPairShape(pair, table, where);
110
- if (!EAV_TIERS.includes(pair.tier)) {
111
- throw new Error(`table ${table}: ${where}.tier ${JSON.stringify(pair.tier)} is not one of ${EAV_TIERS.join(', ')}`);
112
- }
113
- if (!Array.isArray(pair.pinnedKeys) || pair.pinnedKeys.some((k) => typeof k !== 'string')) {
114
- throw new Error(`table ${table}: ${where}.pinnedKeys must be an array of key names`);
115
- }
116
- return { ...shape, tier: pair.tier, pinnedKeys: [...pair.pinnedKeys] };
117
- }
118
-
119
- /**
120
- * query-structure's `eavAccess`. Absent for a table with no key/value pair.
121
- *
122
- * EVERY pair goes through the SAME validation, primary and additional alike. An earlier
123
- * version validated the primary strictly and then copied an additional pair's `tier`
124
- * unchecked while coercing a malformed `pinnedKeys` to `[]` — so a response claiming
125
- * `tier: "full"` on a second pair was accepted, and a caller branching on tier could conclude
126
- * a guarded column was freely readable. Validating one of N is not validating.
127
- */
128
- function assertEavAccess(eavAccess, table) {
129
- if (eavAccess === undefined || eavAccess === null) return null;
130
- const access = assertAccessPair(eavAccess, table, 'eavAccess');
131
- if (eavAccess.additionalPairs !== undefined) {
132
- if (!Array.isArray(eavAccess.additionalPairs)) throw new Error(`table ${table}: eavAccess.additionalPairs must be an array`);
133
- access.additionalPairs = eavAccess.additionalPairs.map((p) => assertAccessPair(p, table, 'eavAccess.additionalPairs[]'));
134
- }
135
- return access;
136
- }
137
-
138
- /** Every pair in an eavAccess, primary first — what any per-pair reasoning should iterate. */
139
- function eavAccessPairs(eavAccess) {
140
- if (!eavAccess) return [];
141
- const { keyColumn, valueColumn, tier, pinnedKeys } = eavAccess;
142
- return [{ keyColumn, valueColumn, tier, pinnedKeys }, ...(eavAccess.additionalPairs || [])];
143
- }
144
-
145
- /**
146
- * Every value column this table guards -- the primary pair's plus any additional ones. What
147
- * a caller needs to build a legal request: these columns are unreachable unless the matching
148
- * key column is pinned.
149
- */
150
- function guardedValueColumns(pairOrAccess) {
151
- if (!pairOrAccess) return [];
152
- return [pairOrAccess.valueColumn, ...(pairOrAccess.additionalPairs || []).map((p) => p.valueColumn)];
153
- }
154
-
155
- /**
156
- * Reports the live column list for one bare table name. Structure only, never row data --
157
- * see modules/class-wmh2-structure-discovery.php's own contract. Throws on any
158
- * malformed/incomplete response rather than returning a partial result silently.
159
- *
160
- * Two credential modes, matching the plugin's own two route registrations for
161
- * `/structure`: the default is the WordPress Application Password path (GET, via the
162
- * caller-supplied `httpClient`). Pass `auth: { type: 'migration-key', migrationKey, siteId,
163
- * migrationId, timeoutMs }` to use the signed-JWT path instead -- required on a source site
164
- * with no WooCommerce, where the Application Password routes are `manage_woocommerce`-gated
165
- * and therefore unusable by any user at all (see "Signed migration-key path" below). That
166
- * mode calls the plugin directly over `fetch` and does not use `httpClient`.
167
- */
168
- async function discoverStructure({ httpClient, siteBaseUrl, auth, table } = {}) {
169
- if (!siteBaseUrl || typeof siteBaseUrl !== 'string') throw new Error('siteBaseUrl is required');
170
- if (!table || typeof table !== 'string' || !/^[A-Za-z0-9_]+$/.test(table)) {
171
- throw new Error('table is required and must be a bare identifier (^[A-Za-z0-9_]+$)');
172
- }
173
-
174
- let body;
175
- if (auth && auth.type === 'migration-key') {
176
- if (!auth.migrationKey || typeof auth.migrationKey !== 'string') {
177
- throw new Error('auth.migrationKey is required for the migration-key credential path');
178
- }
179
- body = await callSignedOperation({
180
- siteBaseUrl,
181
- migrationKey: auth.migrationKey,
182
- operation: 'discover-structure',
183
- route: '/wix-wp-plugin/v2/structure',
184
- siteId: auth.siteId || DEFAULT_MIGRATION_KEY_SITE_ID,
185
- migrationId: auth.migrationId || randomUUID(),
186
- operationClaims: { table },
187
- timeoutMs: auth.timeoutMs,
188
- });
189
- } else {
190
- if (!httpClient || typeof httpClient.get !== 'function') throw new Error('httpClient.get is required');
191
- const base = siteBaseUrl.replace(/\/$/, '');
192
- const response = await httpClient.get(`${base}/wp-json/wix-wp-plugin/v2/structure`, {
193
- params: { table },
194
- auth,
195
- });
196
- body = bodyOf(response);
197
- }
198
- if (!body || body.table !== table || !Array.isArray(body.columns)) {
199
- throw new Error(`table ${table}: response did not match discover-structure's response-payload contract`);
200
- }
201
- for (const column of body.columns) assertColumn(column, table);
202
-
203
- // `eavPair` MUST be propagated. Dropping it here was a real bug: it is the
204
- // caller's only advance warning that this table is key-scoped, so without it a caller
205
- // builds an unscoped "select every column" request and gets a 400 it cannot interpret.
206
- return { table: body.table, columns: body.columns, eavPair: assertEavPair(body.eavPair, table) };
207
- }
208
-
209
- /**
210
- * Runs one structure request. Returns one page of rows plus pagingMetadata -- the caller
211
- * is responsible for looping on `hasNext`/`cursors.next` until a full read completes, same
212
- * cursor-paging contract as any other WordPress source route this skill reads. This client
213
- * does not re-validate the structure request's own shape (table/select/where/groupBy/orderBy)
214
- * beyond requiring a `table` -- the plugin itself re-validates every identifier against a
215
- * live DESCRIBE on every request, so duplicating that here would only create a second copy
216
- * to keep in sync.
217
- *
218
- * Two credential modes, matching the plugin's own two route registrations: the default is
219
- * the WordPress Application Password path (POST /query/admin-key, plain JSON, via the
220
- * caller-supplied `httpClient`). Pass `auth: { type: 'migration-key', migrationKey, siteId,
221
- * migrationId, timeoutMs }` to use the signed-JWT path instead (POST /query, no `/admin-key`
222
- * suffix, JWT body) -- required on a source site with no WooCommerce, where the Application
223
- * Password routes are `manage_woocommerce`-gated and therefore unusable by any user at all.
224
- * That mode calls the plugin directly over `fetch` and does not use `httpClient`; it also
225
- * requires an integer `cursorPaging.limit` on every request (the admin-key path lets the
226
- * server default it), so an omitted `limit` falls back to this module's mirror of
227
- * `WMH2_Contract::DEFAULT_LIMIT`.
228
- *
229
- * `onSourceRead` is the telemetry hook: called once per successful read with the
230
- * counts for THAT read, for the caller to pass to rp-telemetry's `sourceRead()`. Optional, so
231
- * a unit test or a one-off script need not wire telemetry, but every real reader should.
232
- */
233
- async function queryStructure({ httpClient, siteBaseUrl, auth, structureRequest, cursor, limit, onSourceRead } = {}) {
234
- if (!siteBaseUrl || typeof siteBaseUrl !== 'string') throw new Error('siteBaseUrl is required');
235
- if (!structureRequest || typeof structureRequest !== 'object' || typeof structureRequest.table !== 'string') {
236
- throw new Error('structureRequest with a table is required');
237
- }
238
-
239
- let body;
240
- if (auth && auth.type === 'migration-key') {
241
- if (!auth.migrationKey || typeof auth.migrationKey !== 'string') {
242
- throw new Error('auth.migrationKey is required for the migration-key credential path');
243
- }
244
- const cursorPaging = { cursor: cursor === undefined ? null : cursor, limit: limit === undefined ? DEFAULT_QUERY_LIMIT : limit };
245
- body = await callSignedOperation({
246
- siteBaseUrl,
247
- migrationKey: auth.migrationKey,
248
- operation: 'query-structure',
249
- route: '/wix-wp-plugin/v2/query',
250
- siteId: auth.siteId || DEFAULT_MIGRATION_KEY_SITE_ID,
251
- migrationId: auth.migrationId || randomUUID(),
252
- operationClaims: { structureRequest, cursorPaging },
253
- timeoutMs: auth.timeoutMs,
254
- });
255
- } else {
256
- if (!httpClient || typeof httpClient.post !== 'function') throw new Error('httpClient.post is required');
257
- const base = siteBaseUrl.replace(/\/$/, '');
258
- const requestBody = { structureRequest };
259
- if (cursor !== undefined) requestBody.cursor = cursor;
260
- if (limit !== undefined) requestBody.limit = limit;
261
- const response = await httpClient.post(`${base}/wp-json/wix-wp-plugin/v2/query/admin-key`, {
262
- body: JSON.stringify(requestBody),
263
- auth,
264
- });
265
- body = bodyOf(response);
266
- }
267
- if (!body || !Array.isArray(body.rows) || !body.pagingMetadata) {
268
- throw new Error(`table ${structureRequest.table}: response did not match query-structure's response-payload contract`);
269
- }
270
- const { pagingMetadata } = body;
271
- if (typeof pagingMetadata.hasNext !== 'boolean' || typeof pagingMetadata.total !== 'number'
272
- || !pagingMetadata.cursors || !('next' in pagingMetadata.cursors)) {
273
- throw new Error(`table ${structureRequest.table}: pagingMetadata does not match query-structure's response-payload contract`);
274
- }
275
-
276
- // REQUIRED on every response, so its absence is a hard error rather than a
277
- // defaulted zero. A plugin old enough not to send it is a plugin without the value guard
278
- // at all, and silently treating that as "nothing was redacted" would report a guarded read
279
- // that never happened. Refusing names the real problem: upgrade the plugin.
280
- const redactionMetadata = assertRedactionMetadata(body.redactionMetadata, structureRequest.table);
281
-
282
- const eavAccess = assertEavAccess(body.eavAccess, structureRequest.table);
283
- if (onSourceRead) onSourceRead(sourceReadCounts(structureRequest.table, eavAccess, redactionMetadata));
284
- return { rows: body.rows, pagingMetadata, redactionMetadata, eavAccess };
285
- }
286
-
287
- // --- Signed migration-key path ("signed request/response" model, contract version 2) ---------
288
- //
289
- // A WordPress site with no `wc/*` REST namespace has no `manage_woocommerce` capability for
290
- // ANYONE, including an administrator -- the Application Password routes above are then
291
- // structurally unusable, for every user on that site, not just a permissions edge case. The
292
- // signed migration-key path is the only credential the plugin's own connection page ever
293
- // issues that does not depend on that capability: `WMH2_Request_Auth::verify_operation()`
294
- // checks a JWT signature and request-binding claims, never a WordPress capability.
295
- //
296
- // This is a DIFFERENT wire shape from the Application Password routes above, not a header
297
- // swap on the same request: POST only (both operations), a distinct un-suffixed route
298
- // (`/structure`, `/query` -- never `/query/admin-key`), `Content-Type: application/jwt` with
299
- // the compact JWT as the entire raw body (never a JSON envelope), and a signed JWT string
300
- // back rather than a plain JSON object. That is why this path calls `fetch` directly instead
301
- // of going through the caller-supplied `httpClient` the Application Password functions take --
302
- // an httpClient built for "send this JSON, get back that JSON" has no seam for "the body IS
303
- // the credential-bearing artifact". `plugins/wix-wp-plugin-v2/examples/jwt-smoke-test.mjs` is
304
- // the reference implementation this mirrors; reuse its claim set and response validation
305
- // rather than inventing a second one that can drift from the plugin's own contract test
306
- // (`tests/source-wordpress/wix-wp-plugin-v2-jwt-contract-v2-test.js`).
307
-
308
- const JWT_REQUEST_ISSUER = 'wix-siteImportService';
309
- const JWT_REQUEST_AUDIENCE = 'wix-wp-plugin-v2';
310
- const JWT_RESPONSE_ISSUER = 'wix-wp-plugin-v2';
311
- const JWT_RESPONSE_AUDIENCE = 'wix-siteImportService';
312
- const JWT_CONTRACT_VERSION = 2;
313
- const JWT_REQUEST_LIFETIME_SECONDS = 60; // must stay under the plugin's MAX_REQUEST_TOKEN_LIFETIME_SECONDS (120)
314
- const DEFAULT_MIGRATION_KEY_SITE_ID = 'rp-source-wordpress';
315
- const DEFAULT_QUERY_LIMIT = 50; // mirrors WMH2_Contract::DEFAULT_LIMIT; cursorPaging.limit is a required int on this path
316
- const DEFAULT_SIGNED_TIMEOUT_MS = 60000;
317
-
318
- function base64url(value) {
319
- return (Buffer.isBuffer(value) ? value : Buffer.from(value, 'utf8')).toString('base64url');
320
- }
321
-
322
- function base64urlDecode(value) {
323
- return Buffer.from(value, 'base64url');
324
- }
325
-
326
- /** Signs one operation's claims with the migration key. Returns the compact JWT plus the claims, so the caller can bind the response back to this exact request via `jti`. */
327
- function signMigrationKeyRequest({ migrationKey, operation, route, siteId, migrationId, operationClaims }) {
328
- const now = Math.floor(Date.now() / 1000);
329
- const claims = {
330
- iss: JWT_REQUEST_ISSUER,
331
- aud: JWT_REQUEST_AUDIENCE,
332
- site_id: siteId,
333
- migration_id: migrationId,
334
- operation,
335
- contract_version: JWT_CONTRACT_VERSION,
336
- method: 'POST',
337
- route,
338
- ...operationClaims,
339
- iat: now,
340
- nbf: now,
341
- exp: now + JWT_REQUEST_LIFETIME_SECONDS,
342
- jti: randomUUID(),
343
- };
344
- const signingInput = [{ alg: 'HS256', typ: 'JWT' }, claims].map((part) => base64url(JSON.stringify(part))).join('.');
345
- const signature = createHmac('sha256', migrationKey).update(signingInput).digest();
346
- return { token: `${signingInput}.${base64url(signature)}`, requestClaims: claims };
347
- }
348
-
349
- /** Verifies a signed response's signature and every request-binding claim before trusting its payload. Never returns an unverified payload. */
350
- function verifyMigrationKeyResponse({ migrationKey, jwt, requestClaims, operation, siteId, migrationId }) {
351
- const parts = String(jwt).split('.');
352
- if (parts.length !== 3) {
353
- throw new Error(`${operation}: response is not a compact three-part JWT`);
354
- }
355
- const [encodedHeader, encodedPayload, encodedSignature] = parts;
356
- const header = JSON.parse(base64urlDecode(encodedHeader).toString('utf8'));
357
- if (header.alg !== 'HS256') {
358
- throw new Error(`${operation}: unexpected response JWT algorithm ${header.alg}`);
359
- }
360
- const expectedSignature = createHmac('sha256', migrationKey).update(`${encodedHeader}.${encodedPayload}`).digest();
361
- const actualSignature = base64urlDecode(encodedSignature);
362
- if (expectedSignature.length !== actualSignature.length || !timingSafeEqual(expectedSignature, actualSignature)) {
363
- throw new Error(`${operation}: response JWT signature is invalid`);
364
- }
365
- const claims = JSON.parse(base64urlDecode(encodedPayload).toString('utf8'));
366
- if (!claims || typeof claims !== 'object' || Array.isArray(claims)) {
367
- throw new Error(`${operation}: response JWT claims must be an object`);
368
- }
369
- const now = Math.floor(Date.now() / 1000);
370
- const requiredClaims = [
371
- 'iss', 'aud', 'site_id', 'migration_id', 'request_jti', 'operation',
372
- 'contract_version', 'snapshot_id', 'payload', 'iat', 'exp', 'jti',
373
- ];
374
- const allowedClaims = new Set([...requiredClaims, 'wp_installation_id']);
375
- const unknownClaims = Object.keys(claims).filter((name) => !allowedClaims.has(name));
376
- if (unknownClaims.length > 0) {
377
- throw new Error(`${operation}: response JWT contains unknown claim(s): ${unknownClaims.join(', ')}`);
378
- }
379
- const missingClaims = requiredClaims.filter((name) => !Object.prototype.hasOwnProperty.call(claims, name));
380
- if (missingClaims.length > 0) {
381
- throw new Error(`${operation}: response JWT is missing required claim(s): ${missingClaims.join(', ')}`);
382
- }
383
- const expectedClaims = {
384
- iss: JWT_RESPONSE_ISSUER,
385
- aud: JWT_RESPONSE_AUDIENCE,
386
- site_id: siteId,
387
- migration_id: migrationId,
388
- request_jti: requestClaims.jti,
389
- operation,
390
- contract_version: JWT_CONTRACT_VERSION,
391
- };
392
- for (const [name, value] of Object.entries(expectedClaims)) {
393
- if (claims[name] !== value) {
394
- throw new Error(`${operation}: unexpected response claim ${name} (expected ${JSON.stringify(value)}, got ${JSON.stringify(claims[name])})`);
395
- }
396
- }
397
- if (!Number.isInteger(claims.iat)) {
398
- throw new Error(`${operation}: response JWT has no integer iat claim`);
399
- }
400
- if (!Number.isInteger(claims.exp) || claims.exp < now) {
401
- throw new Error(`${operation}: response JWT is expired or has no integer exp claim`);
402
- }
403
- for (const name of ['snapshot_id', 'jti']) {
404
- if (typeof claims[name] !== 'string' || claims[name] === '') {
405
- throw new Error(`${operation}: response JWT claim ${name} must be a non-empty string`);
406
- }
407
- }
408
- if (Object.prototype.hasOwnProperty.call(claims, 'wp_installation_id')
409
- && (typeof claims.wp_installation_id !== 'string' || claims.wp_installation_id === '')) {
410
- throw new Error(`${operation}: response JWT claim wp_installation_id must be a non-empty string when present`);
411
- }
412
- if (!claims.payload || typeof claims.payload !== 'object' || Array.isArray(claims.payload)) {
413
- throw new Error(`${operation}: response JWT has no object payload claim`);
414
- }
415
- return claims.payload;
416
- }
417
-
418
- /** POSTs one signed operation and returns its verified payload. Refuses redirects: a 301/302 can rewrite the physical POST into a GET, which the plugin's own method binding then correctly rejects -- surfacing that as a redirect error is more actionable than the resulting 400. */
419
- async function callSignedOperation({ siteBaseUrl, migrationKey, operation, route, siteId, migrationId, operationClaims, timeoutMs }) {
420
- const base = siteBaseUrl.replace(/\/$/, '');
421
- const { token, requestClaims } = signMigrationKeyRequest({ migrationKey, operation, route, siteId, migrationId, operationClaims });
422
- const effectiveTimeoutMs = Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : DEFAULT_SIGNED_TIMEOUT_MS;
423
- const controller = new AbortController();
424
- const timer = setTimeout(() => controller.abort(), effectiveTimeoutMs);
425
- let response;
426
- try {
427
- response = await fetch(`${base}/wp-json${route}`, {
428
- method: 'POST',
429
- redirect: 'manual',
430
- headers: { accept: 'application/json', 'content-type': 'application/jwt' },
431
- body: token,
432
- signal: controller.signal,
433
- });
434
- } finally {
435
- clearTimeout(timer);
436
- }
437
- if (response.status >= 300 && response.status < 400) {
438
- throw new Error(`${operation}: redirected to ${response.headers.get('location') || '(unknown location)'} -- use the site's canonical HTTPS URL`);
439
- }
440
- const responseText = await response.text();
441
- if (!response.ok) {
442
- const error = new Error(`${operation}: HTTP ${response.status}: ${responseText}`);
443
- error.status = response.status;
444
- throw error;
445
- }
446
- let responseJwt;
447
- try {
448
- responseJwt = JSON.parse(responseText);
449
- } catch {
450
- responseJwt = responseText;
451
- }
452
- if (typeof responseJwt !== 'string') {
453
- throw new Error(`${operation}: response body is not a signed JWT string`);
454
- }
455
- return verifyMigrationKeyResponse({ migrationKey, jwt: responseJwt, requestClaims, operation, siteId, migrationId });
456
- }
457
-
458
- /**
459
- * The per-read telemetry counts, derived HERE because this client is the single point every
460
- * bridge read passes through -- deriving them at any call site would mean every future caller
461
- * has to remember, and the one that forgets makes the run's total quietly wrong.
462
- *
463
- * Note what is NOT in here: key names. A run's own artifacts hold those. `redacted_values` is
464
- * the field worth aggregating across runs, because a non-zero total means some site keeps a
465
- * credential where nobody expected one.
466
- */
467
- function sourceReadCounts(table, eavAccess, redactionMetadata) {
468
- const counts = { redacted_values: redactionMetadata.redactedValueCount };
469
- const pairs = eavAccessPairs(eavAccess);
470
- if (pairs.length > 0) {
471
- // MIXED-TIER RULE, stated rather than left to whichever pair happens to be first: a
472
- // request counts as SCOPED if ANY pair was pinned. The counts answer "how many reads
473
- // returned key/value DATA versus only key names", and one pinned pair means values came
474
- // back — so classifying by the primary pair alone would file a read that returned values
475
- // as a name-only discovery read. Reading the first pair's tier was the earlier behaviour
476
- // and it misclassified exactly this case.
477
- const anyPinned = pairs.some((p) => p.tier === 'key-scoped');
478
- counts[anyPinned ? 'scoped_queries' : 'discovery_queries'] = 1;
479
- counts[anyPinned ? 'scoped_tables' : 'discovery_tables'] = [table];
480
- }
481
- return counts;
482
- }
483
-
484
- /**
485
- * Would this request violate the tier rule -- i.e. does it name a guarded value column without
486
- * pinning that pair's key with `eq`/`in`?
487
- *
488
- * Decided from the request and the schema, NOT from the response, because the plugin answers a
489
- * tier violation with the same 400 as a nonexistent column, a malformed request, or a bad
490
- * cursor -- deliberately, so a refusal never discloses which column holds values. Treating
491
- * every 400 on a key/value table as a tier refusal was the earlier behaviour and it
492
- * misclassified the common case: a profile naming a column the site has since dropped is an
493
- * outdated profile, and filing it as a security-control refusal makes the one number that
494
- * should mean "something tried to reach values it had not named" mean nothing.
495
- *
496
- * Mirrors the plugin's own predicate, which is why it lives beside the client
497
- * rather than at a call site.
498
- *
499
- * @param eavPair discover-structure's `eavPair` (with any `additionalPairs`), or null.
500
- */
501
- function violatesTierRule(structureRequest, eavPair) {
502
- if (!eavPair) return false;
503
- const pairs = [{ keyColumn: eavPair.keyColumn, valueColumn: eavPair.valueColumn }, ...(eavPair.additionalPairs || [])];
504
- const where = Array.isArray(structureRequest.where) ? structureRequest.where : [];
505
- const names = new Set([
506
- ...(structureRequest.select || []).map((item) => item && item.column),
507
- ...where.map((condition) => condition && condition.column),
508
- ...(structureRequest.groupBy || []),
509
- ...(structureRequest.orderBy || []).map((item) => item && item.column),
510
- ]);
511
- return pairs.some(({ keyColumn, valueColumn }) => {
512
- if (!names.has(valueColumn)) return false;
513
- const pinned = where.some((c) => c && c.column === keyColumn && (c.op === 'eq' || c.op === 'in'));
514
- return !pinned;
515
- });
516
- }
517
-
518
- /** A tier-rule refusal, counted separately once `violatesTierRule` has established it is one. */
519
- function recordTierRefusal(onSourceRead) {
520
- if (onSourceRead) onSourceRead({ tier_refusals: 1 });
521
- }
522
-
523
- // Two caps, both the plugin's, both load-bearing here.
524
- const MAX_PINNED_KEYS = 50; // per scoped request
525
- const MAX_PAGE_LIMIT = 200; // per page, WMH2_Contract::MAX_LIMIT
526
- const MAX_SELECT_COLUMNS = 50; // WMH2_Structure_Query::MAX_SELECT_COLUMNS
527
-
528
- /**
529
- * Page the discovery tier to exhaustion and return EVERY distinct key.
530
- *
531
- * Exhaustion is the whole contract. A truncated key list reads as "these are all the keys" and
532
- * sends a mapper down a wrong path, so this either returns a complete list or says plainly that
533
- * it did not: `truncated` is true when `maxKeys` was hit, and a caller must treat that as an
534
- * incomplete extraction rather than a slightly-short one. There is no silent cap.
535
- */
536
- function validateStructureRequest(request) {
537
- const identifier = (value) => typeof value === 'string' && /^[A-Za-z0-9_]+$/.test(value);
538
- const keys = (value, allowed) => value && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).every((key) => allowed.includes(key));
539
- if (!keys(request, ['table', 'select', 'where', 'groupBy', 'orderBy']) || !identifier(request.table)) throw new Error('invalid structure request/table');
540
- if (!Array.isArray(request.select) || !request.select.length || request.select.length > MAX_SELECT_COLUMNS) throw new Error('structure select must contain 1..50 columns');
541
- for (const field of request.select) {
542
- if (!keys(field, ['column', 'aggregate', 'as']) || !identifier(field.column)
543
- || (field.aggregate !== undefined && !['sum', 'count', 'avg', 'min', 'max'].includes(field.aggregate))
544
- || (field.as !== undefined && (typeof field.as !== 'string' || !field.as))) throw new Error('invalid structure select field');
545
- }
546
- if (request.where !== undefined && !Array.isArray(request.where)) throw new Error('structure where must be an array');
547
- validateEavScope(request.where || []);
548
- if (request.groupBy !== undefined && (!Array.isArray(request.groupBy) || request.groupBy.some((column) => !identifier(column)))) throw new Error('invalid structure groupBy');
549
- if (request.groupBy?.length && request.select.some((field) => !field.aggregate && !request.groupBy.includes(field.column))) throw new Error('nonaggregate fields must be grouped');
550
- if (!Array.isArray(request.orderBy) || !request.orderBy.length || request.orderBy.some((item) => !keys(item, ['column', 'direction']) || !identifier(item.column) || !['asc', 'desc'].includes(item.direction))) throw new Error('structure orderBy is required');
551
- return request;
552
- }
553
-
554
- function validateEavScope(scope, reserved = 0) {
555
- if (!Array.isArray(scope) || scope.length + reserved > MAX_WHERE_CONDITIONS) throw new Error('EAV scope exceeds where limit');
556
- const scalar = (value, nullable) => (nullable && value === null) || ['string', 'boolean'].includes(typeof value) || (typeof value === 'number' && Number.isFinite(value));
557
- for (const condition of scope) {
558
- if (!condition || Object.keys(condition).some((key) => !['column', 'op', 'value'].includes(key)) || !Object.hasOwn(condition, 'value')) throw new Error('invalid EAV scope condition');
559
- if (!condition || !/^[A-Za-z0-9_]+$/.test(condition.column)
560
- || !['eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'in'].includes(condition.op)) throw new Error('invalid EAV scope');
561
- if (condition.op === 'in' && (!Array.isArray(condition.value) || condition.value.length < 1 || condition.value.length > MAX_IN_VALUES || condition.value.some((value) => !scalar(value, false)))) throw new Error('EAV scope IN must contain 1..100 scalar values');
562
- if (condition.op !== 'in' && !scalar(condition.value, true)) throw new Error('EAV scope comparison must use a scalar');
563
- }
564
- return scope;
565
- }
566
-
567
- async function discoverEavKeys({ httpClient, siteBaseUrl, auth, table, keyColumn, maxKeys = 10000, onSourceRead, scope = [] } = {}) {
568
- // `maxKeys` bounds how many more PAGES we will fetch, not the exact list length: the check
569
- // runs after exhaustion, so a sweep can return up to one page beyond the cap while still
570
- // being complete. That is the right trade -- the alternative reported a table with exactly
571
- // `maxKeys` keys as truncated and blocked a complete extraction.
572
- const keys = [];
573
- const keyCounts = {};
574
- let cursor = null;
575
- let pages = 0;
576
- let truncated = false;
577
- for (;;) {
578
- // eslint-disable-next-line no-await-in-loop
579
- const page = await queryStructure({
580
- httpClient,
581
- siteBaseUrl,
582
- auth,
583
- structureRequest: {
584
- table,
585
- // The COUNT is not decoration. It is what lets the plan state how many 200-row pages
586
- // each batch will need, so "how expensive is this extraction" is answerable before
587
- // running it rather than discovered while running it.
588
- select: [{ column: keyColumn }, { column: keyColumn, aggregate: 'count', as: 'n' }],
589
- ...(scope.length ? { where: validateEavScope(scope) } : {}),
590
- groupBy: [keyColumn],
591
- orderBy: [{ column: keyColumn, direction: 'asc' }],
592
- },
593
- cursor,
594
- limit: MAX_PAGE_LIMIT,
595
- onSourceRead,
596
- });
597
- pages += 1;
598
- for (const row of page.rows) {
599
- if (typeof row[keyColumn] !== 'string') continue;
600
- keys.push(row[keyColumn]);
601
- const count = Number(row.n);
602
- keyCounts[row[keyColumn]] = Number.isFinite(count) ? count : null;
603
- }
604
- cursor = page.pagingMetadata.cursors.next;
605
- // Exhausted: complete, whatever the count. Checking the cap FIRST reported a table with
606
- // exactly `maxKeys` keys as truncated and blocked a complete extraction from promotion.
607
- if (!cursor) break;
608
- if (keys.length >= maxKeys) { truncated = true; break; }
609
- }
610
- return { keys: [...new Set(keys)], keyCounts, pages, truncated };
611
- }
612
-
613
- /**
614
- * Turn discovered key lists into the exact requests a generated reader runs to extract VALUES.
615
- *
616
- * This exists because "discover the keys, then read them" is two steps, and only the first was
617
- * ever executable from a persisted artifact. Discovery's `structure-request.json` for a
618
- * key/value table deliberately omits the guarded value columns, so a reader that runs it
619
- * verbatim extracts key NAMES and nothing else. The values are the whole point, so the second
620
- * step has to be an artifact too, not a paragraph telling a generator to improvise one.
621
- *
622
- * Three things this has to get right, each of which produced a broken plan when it did not:
623
- *
624
- * 1. **Carry the record identity.** A `postmeta` row is `{meta_key, meta_value}` plus the
625
- * `post_id` it belongs to. Without that column the extraction is a bag of values that cannot
626
- * be attributed to an order, which is worse than no extraction because it looks like data.
627
- * Every non-key, non-value column rides along; once a key is pinned they are all readable.
628
- * 2. **One pair at a time.** Selecting a second pair's value column while pinning only the
629
- * first pair's key is a request the plugin REFUSES (each value answers only to its own key).
630
- * So each pair gets its own key list, its own batches and its own select.
631
- * 3. **Order by something unique.** Pagination here is offset-based, so ordering by a
632
- * non-unique column (the key column, which repeats once per record) lets rows shift between
633
- * pages. Prefer the primary key, then a unique column; fall back to the key column only when
634
- * the table offers nothing better, and say so in the plan.
635
- *
636
- * @param keysByPair { [keyColumn]: string[] } — one discovered key list per pair.
637
- */
638
- function buildEavReadPlan({ table, eavPair, schemaColumns = [], keysByPair, countsByPair = null, batchSize = MAX_PINNED_KEYS, truncated = false, scope = [] }) {
639
- if (!eavPair) throw new Error(`table ${table}: buildEavReadPlan needs the eavPair from discover-structure`);
640
- if (!keysByPair || typeof keysByPair !== 'object') throw new Error(`table ${table}: keysByPair must be an object of keyColumn -> keys[]`);
641
- if (batchSize < 1 || batchSize > MAX_PINNED_KEYS) {
642
- throw new Error(`table ${table}: batchSize must be 1..${MAX_PINNED_KEYS} (the plugin's pinned-key cap)`);
643
- }
644
-
645
- const pairs = [{ keyColumn: eavPair.keyColumn, valueColumn: eavPair.valueColumn }, ...(eavPair.additionalPairs || [])];
646
- const keyColumns = new Set(pairs.map((pair) => pair.keyColumn));
647
- const valueColumns = new Set(pairs.map((pair) => pair.valueColumn));
648
-
649
- const named = schemaColumns.map((column) => (typeof column === 'string' ? { name: column, key: null } : column));
650
- const allIdentity = named.filter((column) => !keyColumns.has(column.name) && !valueColumns.has(column.name));
651
-
652
- // Offset pagination needs a stable, unique sort. Anything else lets a row move between pages.
653
- // ⚠️ MySQL permits MANY NULLs in a unique index, so a NULLABLE unique column can tie and is
654
- // not a stable sort. Only a primary key, or a unique column the schema reports as NOT NULL,
655
- // earns orderByIsUnique. A column whose nullability is unknown does not get the benefit of
656
- // the doubt -- claiming stable pagination and not having it is the failure being avoided.
657
- const uniqueColumn = named.find((c) => c.key === 'primary')
658
- || named.find((c) => c.key === 'unique' && c.nullable === false);
659
- const orderColumn = uniqueColumn ? uniqueColumn.name : null;
660
-
661
- // ⚠️ Two slots are RESERVED for the pair's key and value columns before identity columns are
662
- // taken. Appending them last and truncating the whole list to the select cap silently dropped
663
- // the value column on a table with 49+ identity columns -- a plan that looks complete, runs
664
- // without error, and extracts no values at all. When identity has to be trimmed, the columns
665
- // most likely to identify a record survive: the sort column, then indexed ones, then the rest.
666
- const identityBudget = MAX_SELECT_COLUMNS - 2;
667
- const ranked = [...allIdentity].sort((a, b) => rankIdentity(a, orderColumn) - rankIdentity(b, orderColumn));
668
- const identityColumns = ranked.slice(0, identityBudget).map((column) => column.name);
669
- const droppedIdentityColumns = ranked.slice(identityBudget).map((column) => column.name);
670
-
671
- let batchIndex = 0;
672
- const planPairs = pairs.map((pair) => {
673
- const counts = (countsByPair && countsByPair[pair.keyColumn]) || null;
674
- const keys = [...new Set((keysByPair[pair.keyColumn] || []).filter((k) => typeof k === 'string' && k !== ''))].sort();
675
- // identity + this pair's key + this pair's value, capped at the plugin's select limit. The
676
- // key column rides so a value can be attributed to its key without relying on request order,
677
- // which breaks the moment a key has no rows.
678
- const select = [...identityColumns, pair.keyColumn, pair.valueColumn].map((column) => ({ column }));
679
- const order = orderColumn || pair.keyColumn;
680
- const batches = [];
681
- for (let i = 0; i < keys.length; i += batchSize) {
682
- const batchKeys = keys.slice(i, i + batchSize);
683
- // Rows this batch will return, and therefore pages, when discovery supplied counts.
684
- // null when it did not -- an unknown is reported as unknown, never as zero.
685
- const expectedRows = counts ? batchKeys.reduce((sum, key) => sum + (Number.isFinite(counts[key]) ? counts[key] : 0), 0) : null;
686
- batches.push({
687
- batchIndex: batchIndex++,
688
- keyColumn: pair.keyColumn,
689
- keys: batchKeys,
690
- expectedRows,
691
- expectedPages: expectedRows === null ? null : Math.max(1, Math.ceil(expectedRows / MAX_PAGE_LIMIT)),
692
- structureRequest: {
693
- table,
694
- select,
695
- where: [...validateEavScope(scope, 1), { column: pair.keyColumn, op: 'in', value: batchKeys }],
696
- orderBy: [{ column: order, direction: 'asc' }],
697
- },
698
- });
699
- }
700
- return { ...pair, distinctKeyCount: keys.length, batches };
701
- });
702
-
703
- const plan = {
704
- planVersion: 1,
705
- table,
706
- identityColumns,
707
- // Non-empty means the table is wider than the select cap allows, so extracted rows carry
708
- // less than the full record context. Reported, never silent.
709
- droppedIdentityColumns,
710
- orderColumn: orderColumn || null,
711
- // ⚠️ false means the sort column repeats, so offset pagination can shift rows between
712
- // pages. A reader must treat that extraction as best-effort and say so.
713
- orderByIsUnique: Boolean(orderColumn),
714
- batchSize,
715
- pageLimit: MAX_PAGE_LIMIT,
716
- keysTruncated: truncated,
717
- distinctKeyCount: planPairs.reduce((sum, pair) => sum + pair.distinctKeyCount, 0),
718
- expectedBatches: batchIndex,
719
- // The real request cost, not a batch count: a single batch whose keys hold thousands of
720
- // rows needs many 200-row pages. null when discovery could not supply counts.
721
- expectedScopedRequests: planPairs.every((pair) => pair.batches.every((b) => b.expectedPages !== null))
722
- ? planPairs.reduce((sum, pair) => sum + pair.batches.reduce((n, b) => n + b.expectedPages, 0), 0)
723
- : null,
724
- pairs: planPairs,
725
- };
726
- // Identity for the checkpoint. A resume must be able to tell that the plan it is resuming
727
- // into is the plan it started: discovery can rewrite the plan between runs (the site gained
728
- // or lost keys), and continuing a half-finished extraction against a different batch layout
729
- // silently mixes two reads.
730
- plan.planHash = eavReadPlanHash(plan);
731
- return plan;
732
- }
733
-
734
- // Excluded from the hash. `planHash` because a hash cannot cover itself -- including it made the
735
- // embedded value un-recomputable from the persisted file, so nothing could ever verify it.
736
- // `acknowledgedDroppedColumns` because it is a human annotation ABOUT the plan, not part of the
737
- // read the plan describes; acknowledging an omission must not invalidate an in-flight resume.
738
- //
739
- // ⚠️ That exclusion has a consequence, and it is handled in the MANIFEST rather than here: the
740
- // acknowledgement flips reconciliation from failure to success, so if it lived nowhere else,
741
- // withdrawing it later would leave the plan hash unchanged and an incomplete extraction would
742
- // still look reusable. `eavExtractionIsReusable()` below is where that is caught -- the
743
- // approval is provenance, and provenance belongs with the artifact it approved.
744
- const PLAN_HASH_EXCLUDED_KEYS = new Set(['planHash', 'acknowledgedDroppedColumns']);
745
-
746
- /**
747
- * The canonical hash of a read plan's CONTENT.
748
- *
749
- * One function, used in three places that must agree: stamping the plan at build time,
750
- * re-deriving it from the persisted file before promotion, and checking a checkpoint on resume.
751
- * Three call sites hashing "the plan" three slightly different ways is how an integrity check
752
- * ends up unable to detect anything -- which is exactly what happened when the stamp was taken
753
- * before `planHash` existed and codegen was told to hash the finished file.
754
- *
755
- * Keys are sorted at every level so serialization order cannot change the answer.
756
- */
757
- function eavReadPlanHash(plan) {
758
- const canonical = (value) => {
759
- if (Array.isArray(value)) return value.map(canonical);
760
- if (value && typeof value === 'object') {
761
- return Object.keys(value).sort()
762
- .filter((key) => !PLAN_HASH_EXCLUDED_KEYS.has(key))
763
- .reduce((out, key) => { out[key] = canonical(value[key]); return out; }, {});
764
- }
765
- return value;
766
- };
767
- return createHash('sha256').update(JSON.stringify(canonical(plan))).digest('hex').slice(0, 16);
768
- }
769
-
770
- /**
771
- * Does this plan's embedded hash actually match its contents?
772
- *
773
- * Without this, `planHash` proves only that a checkpoint and a plan carry the same string --
774
- * so editing a batch's request while leaving the hash alone reconciled clean, which is the
775
- * tamper case an integrity check exists to catch.
776
- */
777
- function verifyEavReadPlanIntegrity(plan) {
778
- const actual = eavReadPlanHash(plan);
779
- if (plan.planHash !== actual) {
780
- return `plan ${plan.table} declares planHash ${plan.planHash} but its contents hash to ${actual} -- the plan file was edited after discovery wrote it; regenerate it rather than extracting from it`;
781
- }
782
- return null;
783
- }
784
-
785
- /** Sort key for identity columns when the select cap forces a trim: keep what identifies a row. */
786
- function rankIdentity(column, orderColumn) {
787
- if (column.name === orderColumn) return 0;
788
- if (column.key === 'primary') return 1;
789
- if (column.key === 'unique') return 2;
790
- if (column.key === 'index') return 3;
791
- return 4;
792
- }
793
-
794
- /** Every batch across every pair, in execution order. */
795
- function eavReadPlanBatches(plan) {
796
- return (plan.pairs || []).flatMap((pair) => pair.batches);
797
- }
798
-
799
- /**
800
- * Did a plan's execution actually complete? Returns the problems; empty means clean.
801
- *
802
- * Separate from execution on purpose. "It did not throw" is not completeness, and the earlier
803
- * version of this accepted any non-negative row count, so a one-row extraction of a five-batch
804
- * plan passed. Completeness here means three things, and the third is the one that catches a
805
- * page loop that stopped early:
806
- *
807
- * - every batch the plan expects was run, identified by index, not merely counted;
808
- * - each batch read as many rows as its own first page said it would (`snapshotTotal`);
809
- * - the rows actually written equal the sum of those totals.
810
- *
811
- * @param observed { batches: [{batchIndex, rowsRead, snapshotTotal}], rowsWritten }
812
- */
813
- function reconcileEavReadPlan(plan, observed) {
814
- const problems = [];
815
- const batches = (observed && Array.isArray(observed.batches)) ? observed.batches : null;
816
- if (!batches) return ['reconcileEavReadPlan needs observed.batches: [{batchIndex, rowsRead, snapshotTotal}]'];
817
-
818
- if (plan.keysTruncated) {
819
- problems.push(`key discovery hit its cap, so the key list is INCOMPLETE -- this extraction cannot be treated as whole-table`);
820
- }
821
- if (Array.isArray(plan.droppedIdentityColumns) && plan.droppedIdentityColumns.length > 0
822
- && plan.acknowledgedDroppedColumns !== true) {
823
- problems.push(
824
- `this table is wider than the ${MAX_SELECT_COLUMNS}-column select cap, so ${plan.droppedIdentityColumns.length} column(s) are absent from every extracted row `
825
- + `(${plan.droppedIdentityColumns.join(', ')}). The extraction is INCOMPLETE per record. Either narrow the table's mapping and regenerate the plan with an explicit column choice, `
826
- + 'or set acknowledgedDroppedColumns: true on the plan to record that the omission was chosen deliberately',
827
- );
828
- }
829
- if (plan.orderByIsUnique === false) {
830
- problems.push(`this table has no primary or unique column, so batches were ordered by "${plan.orderColumn}", which repeats -- offset pagination may have shifted rows between pages and the extraction is best-effort`);
831
- }
832
-
833
- // ⚠️ Duplicates and strangers are rejected BEFORE any total is computed. Collapsing them into
834
- // a Map while summing the original array let a resume that re-ran batch 0 report double its
835
- // rows and reconcile clean -- duplicated output, promoted as complete.
836
- const expectedIndices = new Set(eavReadPlanBatches(plan).map((b) => b.batchIndex));
837
- // The plan must first be internally consistent: comparing a checkpoint against a plan whose
838
- // own hash no longer describes it just confirms two strings match.
839
- const tampered = verifyEavReadPlanIntegrity(plan);
840
- if (tampered) return [tampered];
841
-
842
- // ⚠️ REQUIRED, not optional. An optional integrity check is one the documented call path
843
- // forgets to pass, and then two different plans reconcile against each other.
844
- if (observed.planHash === undefined || observed.planHash === null) {
845
- return ['reconcileEavReadPlan requires observed.planHash -- without it a checkpoint from a different plan reconciles clean'];
846
- }
847
- if (observed.planHash !== plan.planHash) {
848
- return [`this checkpoint was written against plan ${observed.planHash}, but the plan on disk is ${plan.planHash} -- discovery rewrote it, so the extraction must restart rather than resume into a different batch layout`];
849
- }
850
-
851
- const seen = new Map();
852
- for (const observation of batches) {
853
- if (!expectedIndices.has(observation.batchIndex)) {
854
- problems.push(`observed batch ${observation.batchIndex} is not in this plan -- the checkpoint belongs to a different plan`);
855
- continue;
856
- }
857
- if (seen.has(observation.batchIndex)) {
858
- problems.push(`batch ${observation.batchIndex} was recorded more than once -- a resume re-ran it and its rows are duplicated in the output`);
859
- continue;
860
- }
861
- seen.set(observation.batchIndex, observation);
862
- }
863
- if (problems.some((p) => /recorded more than once|not in this plan/.test(p))) return problems;
864
-
865
- for (const batch of eavReadPlanBatches(plan)) {
866
- const ran = seen.get(batch.batchIndex);
867
- if (!ran) {
868
- problems.push(`batch ${batch.batchIndex} (${batch.keyColumn}, ${batch.keys.length} key(s)) never ran -- the extraction is partial`);
869
- continue;
870
- }
871
- if (!Number.isInteger(ran.snapshotTotal) || !Number.isInteger(ran.rowsRead)) {
872
- problems.push(`batch ${batch.batchIndex} reported a non-integer rowsRead/snapshotTotal`);
873
- continue;
874
- }
875
- if (ran.rowsRead !== ran.snapshotTotal) {
876
- problems.push(`batch ${batch.batchIndex} read ${ran.rowsRead} of ${ran.snapshotTotal} rows -- its page loop stopped early`);
877
- }
878
- }
879
-
880
- const expectedRows = [...seen.values()].reduce((sum, b) => sum + (Number.isInteger(b.rowsRead) ? b.rowsRead : 0), 0);
881
- if (!Number.isInteger(observed.rowsWritten) || observed.rowsWritten < 0) {
882
- problems.push('rowsWritten must be a non-negative integer');
883
- } else if (observed.rowsWritten !== expectedRows) {
884
- problems.push(`wrote ${observed.rowsWritten} rows but the batches read ${expectedRows} -- the output does not match what was fetched`);
885
- }
886
- return problems;
887
- }
888
-
889
- /**
890
- * What the manifest must record about a completed EAV extraction, so a later run can decide
891
- * whether the file on disk is still usable without re-reading the source.
892
- */
893
- function eavExtractionManifest(plan, { planFile, completedBatches, rowsWritten, extractedAt, ndjsonDigest }) {
894
- if (typeof planFile !== 'string' || planFile === '') {
895
- throw new Error(`table ${plan.table}: eavExtractionManifest needs the planFile it was extracted from`);
896
- }
897
- if (typeof ndjsonDigest !== 'string' || ndjsonDigest === '') {
898
- throw new Error(`table ${plan.table}: eavExtractionManifest needs the ndjsonDigest of the promoted file -- a manifest not bound to its data describes nothing`);
899
- }
900
- return {
901
- kind: 'eav-read-plan',
902
- // Which plan produced this file. The hash proves the CONTENT matches; this says which
903
- // artifact on disk to go and re-hash, which a later run needs before it can compare.
904
- planFile,
905
- planHash: plan.planHash,
906
- completedBatches,
907
- rowsWritten,
908
- // These three qualify what the file CONTAINS, so they travel with it. A consumer must be
909
- // able to learn "rows in this file are missing columns" from the artifact rather than from
910
- // whoever happened to run the extraction.
911
- keysTruncated: Boolean(plan.keysTruncated),
912
- droppedIdentityColumns: plan.droppedIdentityColumns || [],
913
- orderByIsUnique: plan.orderByIsUnique !== false,
914
- // The APPROVAL that allowed an incomplete extraction to promote. Recorded because it is
915
- // deliberately outside planHash: without it here, withdrawing the acknowledgement would
916
- // change nothing a later run could see.
917
- acknowledgedDroppedColumns: plan.acknowledgedDroppedColumns === true,
918
- // Binds the manifest to the ACTUAL FILE. Everything else here describes the read that was
919
- // supposed to happen; this is the only field that says what landed on disk. Without it a
920
- // truncated, replaced or half-written NDJSON sitting beside a perfectly valid manifest is
921
- // accepted, and the manifest's authority is exactly what makes that dangerous.
922
- ndjsonDigest,
923
- extractedAt,
924
- };
925
- }
926
-
927
- /**
928
- * The digest recorded in a manifest and recomputed on reuse. One function so the two can never
929
- * be computed differently -- the same reasoning as eavReadPlanHash().
930
- */
931
- function eavExtractionFileDigest(contents) {
932
- return createHash('sha256').update(contents).digest('hex');
933
- }
934
-
935
- const EAV_MANIFEST_REQUIRED_FIELDS = [
936
- 'planFile', 'planHash', 'completedBatches', 'rowsWritten', 'keysTruncated',
937
- 'droppedIdentityColumns', 'orderByIsUnique', 'acknowledgedDroppedColumns', 'ndjsonDigest',
938
- 'extractedAt',
939
- ];
940
-
941
- /**
942
- * Can an existing extraction be reused, or must it be re-read? Returns the reasons it cannot;
943
- * empty means reuse is safe.
944
- *
945
- * **Re-verifies the recorded extraction rather than trusting that it happened.** An earlier
946
- * version checked only `kind`, `planHash` and the acknowledgement, so a manifest carrying
947
- * nothing but those two fields — or one recording zero completed batches, or a `rowsWritten`
948
- * that matched nothing — was accepted, and a run would skip re-extraction on the strength of a
949
- * manifest that described no extraction at all. A manifest is an assertion about a file; the
950
- * point of reading it is to check the assertion, not to accept it.
951
- *
952
- * So the checks are, in order of what makes later ones meaningless:
953
- * 1. shape — every field present and the right type;
954
- * 2. identity — the plan hash still matches, and the plan matches its own hash;
955
- * 3. completeness — the batches the manifest records must RECONCILE against the plan, the
956
- * same reconciliation the extraction itself had to pass;
957
- * 4. qualifiers — what the manifest says about the file must still be true of the plan;
958
- * 5. approval — the dropped-column acknowledgement, which is outside the hash.
959
- */
960
- function eavExtractionIsReusable(plan, manifest, observed) {
961
- if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest) || manifest.kind !== 'eav-read-plan') {
962
- return ['no EAV extraction manifest -- treat the existing file as stale'];
963
- }
964
-
965
- // ⚠️ REQUIRED, and required for the same reason planHash is: a check the caller may omit is a
966
- // check the caller omits. `observed` is what is actually on disk right now -- the sidecar path
967
- // the caller itself resolved, and the digest and line count of the final file it is deciding
968
- // whether to reuse. Everything else here reasons about a read that was SUPPOSED to happen.
969
- if (!observed || typeof observed !== 'object'
970
- || typeof observed.planFile !== 'string' || observed.planFile === ''
971
- || typeof observed.ndjsonDigest !== 'string' || observed.ndjsonDigest === ''
972
- || !Number.isInteger(observed.ndjsonRowCount) || observed.ndjsonRowCount < 0) {
973
- return ['eavExtractionIsReusable requires observed: { planFile, ndjsonDigest, ndjsonRowCount } read from disk -- without them the manifest is only checked against itself'];
974
- }
975
-
976
- // 1. Shape. Reported all at once, and nothing else runs: reasoning about completeness from a
977
- // manifest that is missing fields produces confident nonsense.
978
- const shape = [];
979
- for (const field of EAV_MANIFEST_REQUIRED_FIELDS) {
980
- if (manifest[field] === undefined || manifest[field] === null) shape.push(`manifest is missing ${field}`);
981
- }
982
- if (shape.length === 0) {
983
- if (typeof manifest.planFile !== 'string' || manifest.planFile === '') shape.push('manifest planFile must be a non-empty string');
984
- if (typeof manifest.ndjsonDigest !== 'string' || manifest.ndjsonDigest === '') shape.push('manifest ndjsonDigest must be a non-empty string');
985
- if (!Array.isArray(manifest.completedBatches)) shape.push('manifest completedBatches must be an array');
986
- if (!Number.isInteger(manifest.rowsWritten) || manifest.rowsWritten < 0) shape.push('manifest rowsWritten must be a non-negative integer');
987
- if (!Array.isArray(manifest.droppedIdentityColumns)) shape.push('manifest droppedIdentityColumns must be an array');
988
- if (typeof manifest.keysTruncated !== 'boolean') shape.push('manifest keysTruncated must be a boolean');
989
- if (typeof manifest.orderByIsUnique !== 'boolean') shape.push('manifest orderByIsUnique must be a boolean');
990
- if (typeof manifest.acknowledgedDroppedColumns !== 'boolean') shape.push('manifest acknowledgedDroppedColumns must be a boolean');
991
- }
992
- if (shape.length > 0) return shape;
993
-
994
- // 2. Identity.
995
- const integrity = verifyEavReadPlanIntegrity(plan);
996
- if (integrity) return [integrity];
997
- if (manifest.planHash !== plan.planHash) {
998
- return [`the plan changed since this file was written (${manifest.planHash} -> ${plan.planHash}) -- re-extract`];
999
- }
1000
-
1001
- const reasons = [];
1002
-
1003
- // 2b. The manifest must describe THESE artifacts, not merely valid-looking ones.
1004
- //
1005
- // ⚠️ `manifest.planFile` is compared against the path the CALLER resolved; it is never opened.
1006
- // A manifest is untrusted input -- it can name `../../something-else.json` -- so treating its
1007
- // path as something to follow would let the file choose what it is validated against.
1008
- if (manifest.planFile !== observed.planFile) {
1009
- reasons.push(`manifest names plan file ${manifest.planFile} but this entity's plan is ${observed.planFile} -- the manifest belongs to a different extraction`);
1010
- }
1011
- if (manifest.ndjsonDigest !== observed.ndjsonDigest) {
1012
- reasons.push('the extracted file does not match the digest its manifest recorded -- it was truncated, replaced or half-written since promotion; re-extract');
1013
- }
1014
- if (manifest.rowsWritten !== observed.ndjsonRowCount) {
1015
- reasons.push(`the extracted file holds ${observed.ndjsonRowCount} row(s) but its manifest recorded ${manifest.rowsWritten} -- re-extract`);
1016
- }
1017
-
1018
- // 3. Completeness -- the same bar the extraction had to clear, applied to what it recorded.
1019
- reasons.push(...reconcileEavReadPlan(plan, {
1020
- planHash: manifest.planHash,
1021
- batches: manifest.completedBatches,
1022
- rowsWritten: manifest.rowsWritten,
1023
- }).map((problem) => `the recorded extraction does not reconcile: ${problem}`));
1024
-
1025
- // 4. Qualifiers. If the manifest says the file was paged on a tying sort key and the plan now
1026
- // says otherwise, one of them is describing a different read.
1027
- if (manifest.keysTruncated !== Boolean(plan.keysTruncated)) {
1028
- reasons.push(`manifest records keysTruncated: ${manifest.keysTruncated}, the plan says ${Boolean(plan.keysTruncated)} -- they describe different reads`);
1029
- }
1030
- if (manifest.orderByIsUnique !== (plan.orderByIsUnique !== false)) {
1031
- reasons.push(`manifest records orderByIsUnique: ${manifest.orderByIsUnique}, the plan says ${plan.orderByIsUnique !== false} -- they describe different reads`);
1032
- }
1033
- const dropped = plan.droppedIdentityColumns || [];
1034
- if (JSON.stringify([...manifest.droppedIdentityColumns].sort()) !== JSON.stringify([...dropped].sort())) {
1035
- reasons.push('manifest and plan disagree about which identity columns were dropped -- re-extract');
1036
- }
1037
-
1038
- // 5. Approval, which is deliberately outside the hash and so cannot be caught by step 2.
1039
- // Both sides are checked. The MANIFEST must record that this file's promotion was approved
1040
- // -- a file with missing columns and no recorded approval was never sanctioned, whatever the
1041
- // plan says today -- and the PLAN must still carry the approval, or it has been withdrawn.
1042
- if (dropped.length > 0 && manifest.acknowledgedDroppedColumns !== true) {
1043
- reasons.push(`this file has ${dropped.length} column(s) missing from every row and its manifest does not record an approval for that -- it was promoted unapproved, so re-extract rather than reuse it`);
1044
- }
1045
- if (dropped.length > 0 && plan.acknowledgedDroppedColumns !== true) {
1046
- reasons.push(`this file was promoted with ${dropped.length} column(s) missing from every row, and that omission is no longer acknowledged -- re-extract or re-acknowledge`);
1047
- }
1048
- if (manifest.acknowledgedDroppedColumns === true && dropped.length === 0) {
1049
- reasons.push('the file was promoted under a dropped-column acknowledgement that the current plan no longer needs -- re-extract so the rows carry the full record');
1050
- }
1051
- return reasons;
1052
- }
1053
-
1054
- module.exports = {
1055
- SHARED_CORE_TABLES_REQUIRING_WHERE,
1056
- validateStructureRequest,
1057
- MAX_IN_VALUES,
1058
- MAX_WHERE_CONDITIONS,
1059
- MAX_PINNED_KEYS,
1060
- MAX_PAGE_LIMIT,
1061
- MAX_SELECT_COLUMNS,
1062
- discoverEavKeys,
1063
- validateEavScope,
1064
- buildEavReadPlan,
1065
- eavReadPlanHash,
1066
- verifyEavReadPlanIntegrity,
1067
- eavExtractionManifest,
1068
- eavExtractionFileDigest,
1069
- eavExtractionIsReusable,
1070
- EAV_MANIFEST_REQUIRED_FIELDS,
1071
- eavReadPlanBatches,
1072
- reconcileEavReadPlan, HANDLER_VERSION, discoverStructure, queryStructure, guardedValueColumns, eavAccessPairs, sourceReadCounts, recordTierRefusal, violatesTierRule,
1073
- signMigrationKeyRequest, verifyMigrationKeyResponse,
1074
- };