openplanr 2.2640.8 → 2.2640.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/dashboard/.vite/manifest.json +1 -1
- package/dist/dashboard/assets/{index-COZ36pFn.js → index-D7R6tnlX.js} +2 -2
- package/dist/dashboard/assets/{index-COZ36pFn.js.map → index-D7R6tnlX.js.map} +1 -1
- package/dist/dashboard/dashboard-manifest.json +8 -8
- package/dist/dashboard/index.html +1 -1
- package/lib/host-packages/adapter-registry.json +5 -5
- package/lib/host-packages/capability-map.json +1 -1
- package/lib/host-packages/claude/.claude-plugin/marketplace.json +2 -2
- package/lib/host-packages/claude/openplanr/.claude-plugin/plugin.json +1 -1
- package/lib/host-packages/claude/openplanr/.openplanr-content.json +165 -33
- package/lib/host-packages/claude/openplanr/README.md +22 -1
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-artifact-shell.mjs +3 -11
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-chunked-workspace-client.mjs +555 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/{design-pako-esm.mjs → design-compression.mjs} +2 -1521
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-document.mjs +133 -12
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-encrypted-workspace-client.mjs +647 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-entities.mjs +17 -67
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-handoff.mjs +14 -16
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/{design-planr-home.mjs → design-loopback-server.mjs} +15 -36
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-owner-custody.mjs +121 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-resource-pack.mjs +698 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-review.mjs +798 -796
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-runtime-home.mjs +39 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-runtime-support-5cb7531bede8.mjs +24 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-share.mjs +138 -765
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/{design-escape.mjs → design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs} +158 -156
- package/lib/host-packages/{openai/openplanr/runtime/design/scripts/design-artifact-sources.mjs → claude/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs} +1 -1
- package/lib/host-packages/{openai/openplanr/runtime/design/scripts/design-bounded-json-data.mjs → claude/openplanr/runtime/design/scripts/design-shared-protocol-contracts-31a760fc.mjs} +241 -454
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-protocol-contracts-75a938cc.mjs +222 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-upload-spool.mjs +198 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design.mjs +12 -5
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +18 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +809 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +5193 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-compression.js +4175 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/05-artifact-sharing.js +65 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/06-artifact-review-ui.js +1755 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/07-artifact-sharing.js +62 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/08-artifact-review-ui.js +2600 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +123 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/package.json +3 -3
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +34 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +992 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +2513 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +1919 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +1759 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +1551 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +1121 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +2183 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +705 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +27 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +13 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-design-review-experience.js +3561 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-studio-shell.js +184 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-interface-primitives.js +5045 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-interface-primitives.js +1698 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-studio-shell.js +455 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-design-studio.js +1844 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +257 -0
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +4966 -0
- package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design.mjs +240 -5192
- package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/claude/openplanr/skills/delegate/scripts/backend-diagnostics.mjs +6 -2
- package/lib/host-packages/cursor/openplanr/.openplanr-content.json +164 -32
- package/lib/host-packages/cursor/openplanr/manifest.json +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/backend-diagnostics.mjs +6 -2
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-artifact-shell.mjs +3 -11
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-chunked-workspace-client.mjs +555 -0
- package/lib/host-packages/{openai/openplanr/runtime/design/scripts/design-pako-esm.mjs → cursor/openplanr/runtime/design/scripts/design-compression.mjs} +2 -1521
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-document.mjs +133 -12
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-encrypted-workspace-client.mjs +647 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-entities.mjs +17 -67
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-handoff.mjs +14 -16
- package/lib/host-packages/{openai/openplanr/runtime/design/scripts/design-planr-home.mjs → cursor/openplanr/runtime/design/scripts/design-loopback-server.mjs} +15 -36
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-owner-custody.mjs +121 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-resource-pack.mjs +698 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-review.mjs +798 -796
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-runtime-home.mjs +39 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-runtime-support-5cb7531bede8.mjs +24 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-share.mjs +138 -765
- package/lib/host-packages/{openai/openplanr/runtime/design/scripts/design-escape.mjs → cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs} +158 -156
- package/lib/host-packages/{claude/openplanr/runtime/design/scripts/design-artifact-sources.mjs → cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs} +1 -1
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/{design-bounded-json-data.mjs → design-shared-protocol-contracts-31a760fc.mjs} +241 -454
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-protocol-contracts-75a938cc.mjs +222 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-upload-spool.mjs +198 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design.mjs +12 -5
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +18 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +809 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +5193 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-compression.js +4175 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/05-artifact-sharing.js +65 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/06-artifact-review-ui.js +1755 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/07-artifact-sharing.js +62 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/08-artifact-review-ui.js +2600 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +123 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/package.json +3 -3
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +34 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +992 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +2513 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +1919 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +1759 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +1551 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +1121 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +2183 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +705 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +27 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +13 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-design-review-experience.js +3561 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-studio-shell.js +184 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-interface-primitives.js +5045 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-interface-primitives.js +1698 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-studio-shell.js +455 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-design-studio.js +1844 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +257 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +4966 -0
- package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design.mjs +240 -5192
- package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/openai/.claude-plugin/marketplace.json +2 -2
- package/lib/host-packages/openai/openplanr/.codex-plugin/plugin.json +1 -1
- package/lib/host-packages/openai/openplanr/.openplanr-content.json +164 -32
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-artifact-shell.mjs +3 -11
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-chunked-workspace-client.mjs +555 -0
- package/lib/host-packages/{cursor/openplanr/runtime/design/scripts/design-pako-esm.mjs → openai/openplanr/runtime/design/scripts/design-compression.mjs} +2 -1521
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-document.mjs +133 -12
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-encrypted-workspace-client.mjs +647 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-entities.mjs +17 -67
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-handoff.mjs +14 -16
- package/lib/host-packages/{cursor/openplanr/runtime/design/scripts/design-planr-home.mjs → openai/openplanr/runtime/design/scripts/design-loopback-server.mjs} +15 -36
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-owner-custody.mjs +121 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-resource-pack.mjs +698 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-review.mjs +798 -796
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-runtime-home.mjs +39 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-runtime-support-5cb7531bede8.mjs +24 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-share.mjs +138 -765
- package/lib/host-packages/{cursor/openplanr/runtime/design/scripts/design-escape.mjs → openai/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs} +158 -156
- package/lib/host-packages/{cursor/openplanr/runtime/design/scripts/design-artifact-sources.mjs → openai/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs} +1 -1
- package/lib/host-packages/{claude/openplanr/runtime/design/scripts/design-bounded-json-data.mjs → openai/openplanr/runtime/design/scripts/design-shared-protocol-contracts-31a760fc.mjs} +241 -454
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-protocol-contracts-75a938cc.mjs +222 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-upload-spool.mjs +198 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design.mjs +12 -5
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +18 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +809 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +5193 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-compression.js +4175 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/05-artifact-sharing.js +65 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/06-artifact-review-ui.js +1755 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/07-artifact-sharing.js +62 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/08-artifact-review-ui.js +2600 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +123 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/package.json +3 -3
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +34 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +992 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +2513 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +1919 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +1759 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +1551 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +1121 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +2183 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +705 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +27 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +13 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-design-review-experience.js +3561 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-studio-shell.js +184 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-interface-primitives.js +5045 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-interface-primitives.js +1698 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-studio-shell.js +455 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-design-studio.js +1844 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +257 -0
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +4966 -0
- package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design.mjs +240 -5192
- package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/openai/openplanr/skills/delegate/scripts/backend-diagnostics.mjs +6 -2
- package/package.json +2 -2
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-generated-b0798298053515fd.mjs +0 -18
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js +0 -5
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js +0 -25597
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-generated-b0798298053515fd.mjs +0 -18
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js +0 -5
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js +0 -25597
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-generated-b0798298053515fd.mjs +0 -18
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js +0 -5
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js +0 -25597
|
@@ -6,21 +6,31 @@ import {
|
|
|
6
6
|
currentDesign,
|
|
7
7
|
hash,
|
|
8
8
|
readJson
|
|
9
|
-
} from "./design-
|
|
9
|
+
} from "./design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs";
|
|
10
|
+
import {
|
|
11
|
+
createEncryptedWorkspaceClient,
|
|
12
|
+
createWorkspaceAddress
|
|
13
|
+
} from "./design-encrypted-workspace-client.mjs";
|
|
10
14
|
import {
|
|
11
15
|
copyUploadSpool,
|
|
12
|
-
createChunkedWorkspaceClient,
|
|
13
|
-
ensurePrivateDirectory,
|
|
14
16
|
persistUploadSpool,
|
|
17
|
+
spoolChunkReader
|
|
18
|
+
} from "./design-upload-spool.mjs";
|
|
19
|
+
import {
|
|
20
|
+
createChunkedWorkspaceClient
|
|
21
|
+
} from "./design-chunked-workspace-client.mjs";
|
|
22
|
+
import {
|
|
23
|
+
ensurePrivateDirectory,
|
|
15
24
|
readCustody,
|
|
16
|
-
spoolChunkReader,
|
|
17
25
|
writeCustody
|
|
18
|
-
} from "./design-
|
|
26
|
+
} from "./design-owner-custody.mjs";
|
|
19
27
|
import {
|
|
20
|
-
acquireStartLock,
|
|
21
28
|
configuredPlanrHome,
|
|
22
29
|
planrHome
|
|
23
|
-
} from "./design-
|
|
30
|
+
} from "./design-runtime-home.mjs";
|
|
31
|
+
import {
|
|
32
|
+
acquireStartLock
|
|
33
|
+
} from "./design-loopback-server.mjs";
|
|
24
34
|
import {
|
|
25
35
|
ARTIFACT_ERROR_CODES,
|
|
26
36
|
PipelineError,
|
|
@@ -28,7 +38,7 @@ import {
|
|
|
28
38
|
digestArtifactEnvelope,
|
|
29
39
|
validateArtifactEnvelope,
|
|
30
40
|
validateArtifactReview
|
|
31
|
-
} from "./design-artifact-
|
|
41
|
+
} from "./design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs";
|
|
32
42
|
import {
|
|
33
43
|
DESIGN_WORKSPACE_API,
|
|
34
44
|
DESIGN_WORKSPACE_CREATE_SCHEMA,
|
|
@@ -38,11 +48,93 @@ import {
|
|
|
38
48
|
DESIGN_WORKSPACE_REVISION_SCHEMA,
|
|
39
49
|
DESIGN_WORKSPACE_SCHEMA,
|
|
40
50
|
DESIGN_WORKSPACE_VERSION,
|
|
41
|
-
assertWorkspaceContract
|
|
51
|
+
assertWorkspaceContract
|
|
52
|
+
} from "./design-shared-protocol-contracts-31a760fc.mjs";
|
|
53
|
+
import {
|
|
42
54
|
canonicalizeJson,
|
|
43
55
|
deepFreeze,
|
|
44
56
|
sha256Hex
|
|
45
|
-
} from "./design-
|
|
57
|
+
} from "./design-shared-protocol-contracts-75a938cc.mjs";
|
|
58
|
+
|
|
59
|
+
// packages/design/lib/design/share-status.mjs
|
|
60
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
61
|
+
import { homedir } from "node:os";
|
|
62
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
63
|
+
|
|
64
|
+
// packages/design/lib/design/workspace-address.mjs
|
|
65
|
+
var DESIGN_SHARE_BASE_URL = "https://share.openplanr.dev";
|
|
66
|
+
var DESIGN_SHARE_REVIEW_PATH = "/d";
|
|
67
|
+
var address = createWorkspaceAddress({
|
|
68
|
+
label: "Design",
|
|
69
|
+
reviewPath: DESIGN_SHARE_REVIEW_PATH,
|
|
70
|
+
defaultBaseUrl: DESIGN_SHARE_BASE_URL
|
|
71
|
+
});
|
|
72
|
+
var normalizeWorkspaceBase = address.normalizeWorkspaceBase;
|
|
73
|
+
var workspaceReviewUrl = (access) => `${address.workspaceReviewUrl(access)}${access.schemaVersion === "2.0.0" ? "?v=2" : ""}`;
|
|
74
|
+
|
|
75
|
+
// packages/design/lib/design/share-status.mjs
|
|
76
|
+
var FORMAT = "openplanr-design-owner-custody";
|
|
77
|
+
function custodyLocation(file, options = {}, { allowMissing = false } = {}) {
|
|
78
|
+
const current = currentDesign(file, options);
|
|
79
|
+
const env = options.env ?? process.env;
|
|
80
|
+
const root = resolve(options.custodyRoot ?? join(planrHome(env), "design-shares"));
|
|
81
|
+
let project = current.root;
|
|
82
|
+
for (let candidate = current.root; dirname(candidate) !== candidate; candidate = dirname(candidate)) {
|
|
83
|
+
if (existsSync(join(candidate, ".git")) || existsSync(join(candidate, ".planr"))) {
|
|
84
|
+
project = candidate;
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const key = hash(`${current.root}
|
|
89
|
+
${current.document.id}`);
|
|
90
|
+
const path = join(root, `${key}.json`);
|
|
91
|
+
const within = relative(project, root);
|
|
92
|
+
if ((!allowMissing || existsSync(path)) && (within === "" || !within.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) && within !== ".." && !isAbsolute(within)))
|
|
93
|
+
throw new Error(
|
|
94
|
+
"Design owner credentials must be stored outside the project. Set PLANR_HOME to a private user-level directory."
|
|
95
|
+
);
|
|
96
|
+
const legacyPath = !options.custodyRoot && !configuredPlanrHome(env) ? join(realpathSync(env.HOME || homedir()), ".openplanr", "design-shares", `${key}.json`) : null;
|
|
97
|
+
return { root, path, current, legacyPath };
|
|
98
|
+
}
|
|
99
|
+
function presentationFingerprint(current) {
|
|
100
|
+
const state = readJson(join(current.root, ".design/studio-state.json"), { state: {} }).state;
|
|
101
|
+
return hash(
|
|
102
|
+
JSON.stringify({
|
|
103
|
+
revision: current.revision,
|
|
104
|
+
selectedVariant: state.selectedVariant ?? current.document.selectedVariant,
|
|
105
|
+
positions: state.positions ?? {},
|
|
106
|
+
verification: current.verification.status
|
|
107
|
+
})
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
var safeStatus = (record, current) => ({
|
|
111
|
+
ok: true,
|
|
112
|
+
shared: Boolean(record),
|
|
113
|
+
title: current.document.title,
|
|
114
|
+
localRevision: current.revision,
|
|
115
|
+
retention: "until-revoked",
|
|
116
|
+
...record ? {
|
|
117
|
+
id: record.custody.id,
|
|
118
|
+
url: workspaceReviewUrl(record.custody),
|
|
119
|
+
revision: record.custody.currentRevision ?? record.publishedRevision ?? null,
|
|
120
|
+
publishedRevision: record.publishedRevision ?? null,
|
|
121
|
+
hasUpdate: record.publishedRevision !== current.revision || record.publishedPresentation !== presentationFingerprint(current),
|
|
122
|
+
epoch: record.custody.epoch,
|
|
123
|
+
commentsPaused: Boolean(record.custody.commentsPaused ?? record.commentsPaused),
|
|
124
|
+
revoked: Boolean(record.revoked),
|
|
125
|
+
deleted: Boolean(record.deleted),
|
|
126
|
+
pending: Boolean(
|
|
127
|
+
record.custody.pendingCreate || record.custody.pendingMutation || record.pendingReviewMetadata?.length
|
|
128
|
+
),
|
|
129
|
+
pendingAction: record.custody.pendingCreate ? "create" : record.custody.pendingMutation?.action ?? (record.pendingReviewMetadata?.length ? "review-metadata" : null),
|
|
130
|
+
pendingReviewMetadata: Boolean(record.pendingReviewMetadata?.length)
|
|
131
|
+
} : {}
|
|
132
|
+
});
|
|
133
|
+
function getDesignShareStatus(file, options = {}) {
|
|
134
|
+
const { path, current, legacyPath } = custodyLocation(file, options);
|
|
135
|
+
const record = readCustody(path, { label: "Design", format: FORMAT }) ?? (legacyPath ? readCustody(legacyPath, { label: "Design", format: FORMAT }) : null);
|
|
136
|
+
return safeStatus(record, current);
|
|
137
|
+
}
|
|
46
138
|
|
|
47
139
|
// packages/design/lib/design/share.mjs
|
|
48
140
|
import {
|
|
@@ -59,18 +151,18 @@ import { basename, dirname as dirname4, join as join3, resolve as resolve3 } fro
|
|
|
59
151
|
|
|
60
152
|
// packages/artifact/lib/artifact/import.mjs
|
|
61
153
|
import {
|
|
62
|
-
existsSync as
|
|
154
|
+
existsSync as existsSync3,
|
|
63
155
|
lstatSync as lstatSync2,
|
|
64
156
|
mkdirSync as mkdirSync2,
|
|
65
157
|
readFileSync as readFileSync2,
|
|
66
|
-
realpathSync,
|
|
158
|
+
realpathSync as realpathSync2,
|
|
67
159
|
renameSync as renameSync2,
|
|
68
160
|
rmSync as rmSync2,
|
|
69
161
|
statSync as statSync2,
|
|
70
162
|
writeFileSync as writeFileSync2
|
|
71
163
|
} from "node:fs";
|
|
72
|
-
import { homedir } from "node:os";
|
|
73
|
-
import { dirname as
|
|
164
|
+
import { homedir as homedir2 } from "node:os";
|
|
165
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve2 } from "node:path";
|
|
74
166
|
|
|
75
167
|
// packages/artifact/lib/artifact/internal/feedback.mjs
|
|
76
168
|
var FEEDBACK_FILE = "feedback.json";
|
|
@@ -308,7 +400,7 @@ function effectiveReviewDecision(value) {
|
|
|
308
400
|
// packages/artifact/lib/artifact/review.mjs
|
|
309
401
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
310
402
|
import {
|
|
311
|
-
existsSync,
|
|
403
|
+
existsSync as existsSync2,
|
|
312
404
|
lstatSync,
|
|
313
405
|
mkdirSync,
|
|
314
406
|
readFileSync,
|
|
@@ -317,7 +409,7 @@ import {
|
|
|
317
409
|
statSync,
|
|
318
410
|
writeFileSync
|
|
319
411
|
} from "node:fs";
|
|
320
|
-
import { dirname } from "node:path";
|
|
412
|
+
import { dirname as dirname2 } from "node:path";
|
|
321
413
|
var ARTIFACT_REVIEW_MAX_STATE_BYTES = 5 * 1024 * 1024;
|
|
322
414
|
var reviewPathQueues = /* @__PURE__ */ new Map();
|
|
323
415
|
function finalEntry(path, fs = { lstatSync }) {
|
|
@@ -412,7 +504,7 @@ function readArtifactReviewState(path, { allowMissing = false } = {}) {
|
|
|
412
504
|
}
|
|
413
505
|
function writeArtifactReviewState(path, ledger, { fileSystem = {}, suffix = `${process.pid}.${randomBytes(8).toString("hex")}` } = {}) {
|
|
414
506
|
validateReviewLedger(ledger);
|
|
415
|
-
const fs = { existsSync, lstatSync, mkdirSync, writeFileSync, renameSync, rmSync, ...fileSystem };
|
|
507
|
+
const fs = { existsSync: existsSync2, lstatSync, mkdirSync, writeFileSync, renameSync, rmSync, ...fileSystem };
|
|
416
508
|
const temporary = `${path}.${suffix}.tmp`;
|
|
417
509
|
const serialized = serializeReviewState(ledger);
|
|
418
510
|
if (Buffer.byteLength(serialized, "utf8") > ARTIFACT_REVIEW_MAX_STATE_BYTES) {
|
|
@@ -427,7 +519,7 @@ function writeArtifactReviewState(path, ledger, { fileSystem = {}, suffix = `${p
|
|
|
427
519
|
const target = initial;
|
|
428
520
|
if (target.isSymbolicLink() || !target.isFile()) throw new Error("unsafe final target");
|
|
429
521
|
}
|
|
430
|
-
fs.mkdirSync(
|
|
522
|
+
fs.mkdirSync(dirname2(path), { recursive: true, mode: 448 });
|
|
431
523
|
fs.writeFileSync(temporary, serialized, { mode: 384, flag: "wx" });
|
|
432
524
|
const final = finalEntry(path, fs);
|
|
433
525
|
if (final) {
|
|
@@ -588,12 +680,12 @@ function pathEntry(path, fs = { lstatSync: lstatSync2 }) {
|
|
|
588
680
|
}
|
|
589
681
|
}
|
|
590
682
|
function inside(base, candidate) {
|
|
591
|
-
const rel =
|
|
592
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
683
|
+
const rel = relative2(base, candidate);
|
|
684
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
|
|
593
685
|
}
|
|
594
686
|
function parseablePlanrConfig(root) {
|
|
595
|
-
const path =
|
|
596
|
-
if (!
|
|
687
|
+
const path = join2(root, ".planr", "config.json");
|
|
688
|
+
if (!existsSync3(path)) return false;
|
|
597
689
|
try {
|
|
598
690
|
if (lstatSync2(path).isSymbolicLink()) return false;
|
|
599
691
|
const value = JSON.parse(readFileSync2(path, "utf8"));
|
|
@@ -603,20 +695,20 @@ function parseablePlanrConfig(root) {
|
|
|
603
695
|
}
|
|
604
696
|
}
|
|
605
697
|
function hasGitMarker(root) {
|
|
606
|
-
const marker =
|
|
607
|
-
if (!
|
|
698
|
+
const marker = join2(root, ".git");
|
|
699
|
+
if (!existsSync3(marker)) return false;
|
|
608
700
|
try {
|
|
609
701
|
const stat = lstatSync2(marker);
|
|
610
702
|
if (stat.isSymbolicLink()) return false;
|
|
611
703
|
if (stat.isDirectory()) {
|
|
612
|
-
const head =
|
|
613
|
-
return
|
|
704
|
+
const head = join2(marker, "HEAD");
|
|
705
|
+
return existsSync3(head) && lstatSync2(head).isFile();
|
|
614
706
|
}
|
|
615
707
|
if (!stat.isFile() || stat.size > 4096) return false;
|
|
616
708
|
const match = /^gitdir:\s*(.+?)\s*$/u.exec(readFileSync2(marker, "utf8"));
|
|
617
709
|
if (!match) return false;
|
|
618
|
-
const gitDir =
|
|
619
|
-
return
|
|
710
|
+
const gitDir = resolve2(root, match[1]);
|
|
711
|
+
return existsSync3(gitDir) && statSync2(gitDir).isDirectory() && existsSync3(join2(gitDir, "HEAD")) && lstatSync2(join2(gitDir, "HEAD")).isFile();
|
|
620
712
|
} catch {
|
|
621
713
|
return false;
|
|
622
714
|
}
|
|
@@ -624,37 +716,37 @@ function hasGitMarker(root) {
|
|
|
624
716
|
function findArtifactProjectRoot(start = process.cwd(), { env = process.env } = {}) {
|
|
625
717
|
let current;
|
|
626
718
|
try {
|
|
627
|
-
current =
|
|
719
|
+
current = realpathSync2(resolve2(start));
|
|
628
720
|
} catch {
|
|
629
721
|
pathError(
|
|
630
722
|
ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
|
|
631
723
|
"Artifact review working directory does not exist."
|
|
632
724
|
);
|
|
633
725
|
}
|
|
634
|
-
const homeCandidate =
|
|
726
|
+
const homeCandidate = resolve2(env.HOME ?? homedir2());
|
|
635
727
|
let home = homeCandidate;
|
|
636
728
|
try {
|
|
637
|
-
home =
|
|
729
|
+
home = realpathSync2(homeCandidate);
|
|
638
730
|
} catch {
|
|
639
731
|
}
|
|
640
732
|
while (true) {
|
|
641
733
|
if (current !== home && (parseablePlanrConfig(current) || hasGitMarker(current)))
|
|
642
734
|
return current;
|
|
643
|
-
const parent =
|
|
735
|
+
const parent = dirname3(current);
|
|
644
736
|
if (parent === current) return null;
|
|
645
737
|
current = parent;
|
|
646
738
|
}
|
|
647
739
|
}
|
|
648
740
|
function assertSafeDestination(base, relativeParts) {
|
|
649
|
-
const absoluteBase =
|
|
650
|
-
if (
|
|
741
|
+
const absoluteBase = resolve2(base);
|
|
742
|
+
if (existsSync3(absoluteBase) && lstatSync2(absoluteBase).isSymbolicLink()) {
|
|
651
743
|
pathError(
|
|
652
744
|
ARTIFACT_ERROR_CODES.SYMLINK_ESCAPE,
|
|
653
745
|
"Artifact review destination base is a symlink."
|
|
654
746
|
);
|
|
655
747
|
}
|
|
656
748
|
let realBase = absoluteBase;
|
|
657
|
-
if (
|
|
749
|
+
if (existsSync3(absoluteBase)) realBase = realpathSync2(absoluteBase);
|
|
658
750
|
let current = absoluteBase;
|
|
659
751
|
for (const part of relativeParts) {
|
|
660
752
|
if (!part || part === "." || part === ".." || part.includes("/") || part.includes("\\") || part.includes("\0")) {
|
|
@@ -663,7 +755,7 @@ function assertSafeDestination(base, relativeParts) {
|
|
|
663
755
|
"Artifact review destination contains an unsafe segment."
|
|
664
756
|
);
|
|
665
757
|
}
|
|
666
|
-
current =
|
|
758
|
+
current = join2(current, part);
|
|
667
759
|
const entry = pathEntry(current);
|
|
668
760
|
if (!entry) continue;
|
|
669
761
|
if (entry.isSymbolicLink()) {
|
|
@@ -672,7 +764,7 @@ function assertSafeDestination(base, relativeParts) {
|
|
|
672
764
|
"Artifact review destination contains a symlink."
|
|
673
765
|
);
|
|
674
766
|
}
|
|
675
|
-
if (!inside(realBase,
|
|
767
|
+
if (!inside(realBase, realpathSync2(current))) {
|
|
676
768
|
pathError(
|
|
677
769
|
ARTIFACT_ERROR_CODES.PATH_TRAVERSAL,
|
|
678
770
|
"Artifact review destination escapes its storage root."
|
|
@@ -700,8 +792,8 @@ function resolveArtifactReviewDestination({
|
|
|
700
792
|
);
|
|
701
793
|
}
|
|
702
794
|
if (designDir !== void 0) {
|
|
703
|
-
const lexical =
|
|
704
|
-
if (!
|
|
795
|
+
const lexical = resolve2(designDir);
|
|
796
|
+
if (!existsSync3(lexical) || !statSync2(lexical).isDirectory()) {
|
|
705
797
|
pathError(ARTIFACT_ERROR_CODES.REVIEW_IMPORT, "Design review destination does not exist.");
|
|
706
798
|
}
|
|
707
799
|
if (lstatSync2(lexical).isSymbolicLink()) {
|
|
@@ -710,13 +802,13 @@ function resolveArtifactReviewDestination({
|
|
|
710
802
|
"Design review destination must be a real directory."
|
|
711
803
|
);
|
|
712
804
|
}
|
|
713
|
-
const requested =
|
|
805
|
+
const requested = realpathSync2(lexical);
|
|
714
806
|
return Object.freeze({
|
|
715
807
|
kind: "design",
|
|
716
808
|
artifactId,
|
|
717
809
|
directory: requested,
|
|
718
|
-
path:
|
|
719
|
-
reviewStatePath:
|
|
810
|
+
path: join2(requested, FEEDBACK_FILE),
|
|
811
|
+
reviewStatePath: join2(requested, "artifact-review-state.json")
|
|
720
812
|
});
|
|
721
813
|
}
|
|
722
814
|
const projectRoot = findArtifactProjectRoot(cwd, { env });
|
|
@@ -727,17 +819,17 @@ function resolveArtifactReviewDestination({
|
|
|
727
819
|
artifactId,
|
|
728
820
|
root: projectRoot,
|
|
729
821
|
directory: directory2,
|
|
730
|
-
path:
|
|
822
|
+
path: join2(directory2, "review-state.json")
|
|
731
823
|
});
|
|
732
824
|
}
|
|
733
|
-
const root =
|
|
825
|
+
const root = resolve2(planrHome(env));
|
|
734
826
|
const directory = assertSafeDestination(root, ["artifacts", artifactId]);
|
|
735
827
|
return Object.freeze({
|
|
736
828
|
kind: "user",
|
|
737
829
|
artifactId,
|
|
738
830
|
root,
|
|
739
831
|
directory,
|
|
740
|
-
path:
|
|
832
|
+
path: join2(directory, "review-state.json")
|
|
741
833
|
});
|
|
742
834
|
}
|
|
743
835
|
function reviewsFromDecoded(value) {
|
|
@@ -820,724 +912,6 @@ async function decodeArtifactReviewSources(sources, { decodeSource, withMetadata
|
|
|
820
912
|
return withMetadata ? entries : entries.map((entry) => entry.review);
|
|
821
913
|
}
|
|
822
914
|
|
|
823
|
-
// packages/design/lib/design/share-status.mjs
|
|
824
|
-
import { existsSync as existsSync3, realpathSync as realpathSync2 } from "node:fs";
|
|
825
|
-
import { homedir as homedir2 } from "node:os";
|
|
826
|
-
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve2 } from "node:path";
|
|
827
|
-
|
|
828
|
-
// packages/artifact/lib/artifact/internal/workspace-address.mjs
|
|
829
|
-
function createWorkspaceAddress({
|
|
830
|
-
label,
|
|
831
|
-
reviewPath,
|
|
832
|
-
defaultBaseUrl = "https://share.openplanr.dev"
|
|
833
|
-
}) {
|
|
834
|
-
function normalizeWorkspaceBase2(baseUrl = defaultBaseUrl) {
|
|
835
|
-
const url = new URL(baseUrl);
|
|
836
|
-
if (url.username || url.password || url.search || url.hash || url.pathname !== "/" || url.protocol !== "https:" && !(url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname)))
|
|
837
|
-
throw new TypeError(
|
|
838
|
-
`${label} sharing requires an HTTPS origin or a local development server.`
|
|
839
|
-
);
|
|
840
|
-
return url.origin;
|
|
841
|
-
}
|
|
842
|
-
function workspaceReviewUrl2(access) {
|
|
843
|
-
if (!/^[A-Za-z0-9_-]{22,64}$/.test(access.id))
|
|
844
|
-
throw new TypeError(`Invalid ${label.toLowerCase()} workspace identity.`);
|
|
845
|
-
return `${normalizeWorkspaceBase2(access.baseUrl)}${reviewPath}/${access.id}`;
|
|
846
|
-
}
|
|
847
|
-
return { normalizeWorkspaceBase: normalizeWorkspaceBase2, workspaceReviewUrl: workspaceReviewUrl2 };
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
// packages/design/lib/design/workspace-address.mjs
|
|
851
|
-
var DESIGN_SHARE_BASE_URL = "https://share.openplanr.dev";
|
|
852
|
-
var DESIGN_SHARE_REVIEW_PATH = "/d";
|
|
853
|
-
var address = createWorkspaceAddress({
|
|
854
|
-
label: "Design",
|
|
855
|
-
reviewPath: DESIGN_SHARE_REVIEW_PATH,
|
|
856
|
-
defaultBaseUrl: DESIGN_SHARE_BASE_URL
|
|
857
|
-
});
|
|
858
|
-
var normalizeWorkspaceBase = address.normalizeWorkspaceBase;
|
|
859
|
-
var workspaceReviewUrl = (access) => `${address.workspaceReviewUrl(access)}${access.schemaVersion === "2.0.0" ? "?v=2" : ""}`;
|
|
860
|
-
|
|
861
|
-
// packages/design/lib/design/share-status.mjs
|
|
862
|
-
var FORMAT = "openplanr-design-owner-custody";
|
|
863
|
-
function custodyLocation(file, options = {}, { allowMissing = false } = {}) {
|
|
864
|
-
const current = currentDesign(file, options);
|
|
865
|
-
const env = options.env ?? process.env;
|
|
866
|
-
const root = resolve2(options.custodyRoot ?? join2(planrHome(env), "design-shares"));
|
|
867
|
-
let project = current.root;
|
|
868
|
-
for (let candidate = current.root; dirname3(candidate) !== candidate; candidate = dirname3(candidate)) {
|
|
869
|
-
if (existsSync3(join2(candidate, ".git")) || existsSync3(join2(candidate, ".planr"))) {
|
|
870
|
-
project = candidate;
|
|
871
|
-
break;
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
const key = hash(`${current.root}
|
|
875
|
-
${current.document.id}`);
|
|
876
|
-
const path = join2(root, `${key}.json`);
|
|
877
|
-
const within = relative2(project, root);
|
|
878
|
-
if ((!allowMissing || existsSync3(path)) && (within === "" || !within.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) && within !== ".." && !isAbsolute2(within)))
|
|
879
|
-
throw new Error(
|
|
880
|
-
"Design owner credentials must be stored outside the project. Set PLANR_HOME to a private user-level directory."
|
|
881
|
-
);
|
|
882
|
-
const legacyPath = !options.custodyRoot && !configuredPlanrHome(env) ? join2(realpathSync2(env.HOME || homedir2()), ".openplanr", "design-shares", `${key}.json`) : null;
|
|
883
|
-
return { root, path, current, legacyPath };
|
|
884
|
-
}
|
|
885
|
-
function presentationFingerprint(current) {
|
|
886
|
-
const state = readJson(join2(current.root, ".design/studio-state.json"), { state: {} }).state;
|
|
887
|
-
return hash(
|
|
888
|
-
JSON.stringify({
|
|
889
|
-
revision: current.revision,
|
|
890
|
-
selectedVariant: state.selectedVariant ?? current.document.selectedVariant,
|
|
891
|
-
positions: state.positions ?? {},
|
|
892
|
-
verification: current.verification.status
|
|
893
|
-
})
|
|
894
|
-
);
|
|
895
|
-
}
|
|
896
|
-
var safeStatus = (record, current) => ({
|
|
897
|
-
ok: true,
|
|
898
|
-
shared: Boolean(record),
|
|
899
|
-
title: current.document.title,
|
|
900
|
-
localRevision: current.revision,
|
|
901
|
-
retention: "until-revoked",
|
|
902
|
-
...record ? {
|
|
903
|
-
id: record.custody.id,
|
|
904
|
-
url: workspaceReviewUrl(record.custody),
|
|
905
|
-
revision: record.custody.currentRevision ?? record.publishedRevision ?? null,
|
|
906
|
-
publishedRevision: record.publishedRevision ?? null,
|
|
907
|
-
hasUpdate: record.publishedRevision !== current.revision || record.publishedPresentation !== presentationFingerprint(current),
|
|
908
|
-
epoch: record.custody.epoch,
|
|
909
|
-
commentsPaused: Boolean(record.custody.commentsPaused ?? record.commentsPaused),
|
|
910
|
-
revoked: Boolean(record.revoked),
|
|
911
|
-
deleted: Boolean(record.deleted),
|
|
912
|
-
pending: Boolean(
|
|
913
|
-
record.custody.pendingCreate || record.custody.pendingMutation || record.pendingReviewMetadata?.length
|
|
914
|
-
),
|
|
915
|
-
pendingAction: record.custody.pendingCreate ? "create" : record.custody.pendingMutation?.action ?? (record.pendingReviewMetadata?.length ? "review-metadata" : null),
|
|
916
|
-
pendingReviewMetadata: Boolean(record.pendingReviewMetadata?.length)
|
|
917
|
-
} : {}
|
|
918
|
-
});
|
|
919
|
-
function getDesignShareStatus(file, options = {}) {
|
|
920
|
-
const { path, current, legacyPath } = custodyLocation(file, options);
|
|
921
|
-
const record = readCustody(path, { label: "Design", format: FORMAT }) ?? (legacyPath ? readCustody(legacyPath, { label: "Design", format: FORMAT }) : null);
|
|
922
|
-
return safeStatus(record, current);
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
// packages/artifact/lib/artifact/encrypted-workspace-client.mjs
|
|
926
|
-
function createEncryptedWorkspaceClient({
|
|
927
|
-
domain,
|
|
928
|
-
apiPath,
|
|
929
|
-
reviewPath,
|
|
930
|
-
label,
|
|
931
|
-
compatibilityMessage,
|
|
932
|
-
compatibilityCode = "E_WORKSPACE_UNSUPPORTED",
|
|
933
|
-
defaultBaseUrl = "https://share.openplanr.dev",
|
|
934
|
-
version = "1.0.0",
|
|
935
|
-
maxBytes = 5 * 1024 * 1024,
|
|
936
|
-
maxEventBytes = 256 * 1024,
|
|
937
|
-
schemas,
|
|
938
|
-
assertContract,
|
|
939
|
-
assertBundle,
|
|
940
|
-
assertFeedback,
|
|
941
|
-
bundleDigest,
|
|
942
|
-
digestInput = (bundle) => bundle,
|
|
943
|
-
packBundle = async (bundle) => bundle,
|
|
944
|
-
unpackBundle = async (bundle) => bundle
|
|
945
|
-
}) {
|
|
946
|
-
if (!domain || !apiPath?.startsWith("/") || !reviewPath?.startsWith("/") || !label)
|
|
947
|
-
throw new TypeError("An encrypted workspace requires an explicit domain and routes.");
|
|
948
|
-
const encoder2 = new TextEncoder();
|
|
949
|
-
const decoder2 = new TextDecoder("utf-8", { fatal: true });
|
|
950
|
-
const tokenPattern = /^[A-Za-z0-9_-]{43}$/;
|
|
951
|
-
const idPattern = /^[A-Za-z0-9_-]{22,64}$/;
|
|
952
|
-
const ec = { name: "ECDSA", namedCurve: "P-256" };
|
|
953
|
-
const signatureAlgorithm = { name: "ECDSA", hash: "SHA-256" };
|
|
954
|
-
const omitSignature = ({ signature: _signature, ...value }) => value;
|
|
955
|
-
const operationError = (message, code, status) => Object.assign(new Error(message), { code, ...status ? { status } : {} });
|
|
956
|
-
function encodeWorkspaceBytes2(bytes) {
|
|
957
|
-
let binary = "";
|
|
958
|
-
for (let offset = 0; offset < bytes.length; offset += 8192)
|
|
959
|
-
binary += String.fromCharCode(...bytes.subarray(offset, offset + 8192));
|
|
960
|
-
return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "");
|
|
961
|
-
}
|
|
962
|
-
function decodeWorkspaceBytes2(value) {
|
|
963
|
-
if (typeof value !== "string" || !/^[A-Za-z0-9_-]+$/u.test(value))
|
|
964
|
-
throw new TypeError("Invalid encoded workspace value.");
|
|
965
|
-
const decoded = Uint8Array.from(
|
|
966
|
-
atob(value.replaceAll("-", "+").replaceAll("_", "/")),
|
|
967
|
-
(char) => char.charCodeAt(0)
|
|
968
|
-
);
|
|
969
|
-
if (encodeWorkspaceBytes2(decoded) !== value)
|
|
970
|
-
throw new TypeError("Noncanonical encoded workspace value.");
|
|
971
|
-
return decoded;
|
|
972
|
-
}
|
|
973
|
-
function newWorkspaceToken2() {
|
|
974
|
-
return encodeWorkspaceBytes2(crypto.getRandomValues(new Uint8Array(32)));
|
|
975
|
-
}
|
|
976
|
-
function newWorkspaceId2() {
|
|
977
|
-
return encodeWorkspaceBytes2(crypto.getRandomValues(new Uint8Array(18)));
|
|
978
|
-
}
|
|
979
|
-
const { normalizeWorkspaceBase: normalizeWorkspaceBase2, workspaceReviewUrl: workspaceReviewUrl2 } = createWorkspaceAddress({
|
|
980
|
-
label,
|
|
981
|
-
reviewPath,
|
|
982
|
-
defaultBaseUrl
|
|
983
|
-
});
|
|
984
|
-
async function tokenMaterial(token, id, purpose) {
|
|
985
|
-
if (!tokenPattern.test(token) || decodeWorkspaceBytes2(token).length !== 32 || !idPattern.test(id))
|
|
986
|
-
throw new TypeError("Enter the complete generated access token.");
|
|
987
|
-
const key = await crypto.subtle.importKey("raw", decodeWorkspaceBytes2(token), "HKDF", false, [
|
|
988
|
-
"deriveBits"
|
|
989
|
-
]);
|
|
990
|
-
return new Uint8Array(
|
|
991
|
-
await crypto.subtle.deriveBits(
|
|
992
|
-
{
|
|
993
|
-
name: "HKDF",
|
|
994
|
-
hash: "SHA-256",
|
|
995
|
-
salt: encoder2.encode(id),
|
|
996
|
-
info: encoder2.encode(`${domain}/${purpose}`)
|
|
997
|
-
},
|
|
998
|
-
key,
|
|
999
|
-
256
|
|
1000
|
-
)
|
|
1001
|
-
);
|
|
1002
|
-
}
|
|
1003
|
-
async function deriveWorkspaceAuthentication2(token, id) {
|
|
1004
|
-
return encodeWorkspaceBytes2(await tokenMaterial(token, id, "reviewer-auth"));
|
|
1005
|
-
}
|
|
1006
|
-
function canonicalWorkspacePublicKey2(value) {
|
|
1007
|
-
if (value?.kty !== "EC" || value.crv !== "P-256" || !tokenPattern.test(value.x ?? "") || !tokenPattern.test(value.y ?? "") || "d" in value) {
|
|
1008
|
-
throw new TypeError(`Invalid ${label.toLowerCase()} workspace public key.`);
|
|
1009
|
-
}
|
|
1010
|
-
return { kty: "EC", crv: "P-256", x: value.x, y: value.y };
|
|
1011
|
-
}
|
|
1012
|
-
async function createWorkspaceSigner2() {
|
|
1013
|
-
const pair = await crypto.subtle.generateKey(ec, true, ["sign", "verify"]);
|
|
1014
|
-
return {
|
|
1015
|
-
privateKey: encodeWorkspaceBytes2(
|
|
1016
|
-
new Uint8Array(await crypto.subtle.exportKey("pkcs8", pair.privateKey))
|
|
1017
|
-
),
|
|
1018
|
-
publicKey: canonicalWorkspacePublicKey2(await crypto.subtle.exportKey("jwk", pair.publicKey))
|
|
1019
|
-
};
|
|
1020
|
-
}
|
|
1021
|
-
async function signWorkspaceValue2(value, privateKey) {
|
|
1022
|
-
const key = await crypto.subtle.importKey(
|
|
1023
|
-
"pkcs8",
|
|
1024
|
-
decodeWorkspaceBytes2(privateKey),
|
|
1025
|
-
ec,
|
|
1026
|
-
false,
|
|
1027
|
-
["sign"]
|
|
1028
|
-
);
|
|
1029
|
-
const signature = await crypto.subtle.sign(
|
|
1030
|
-
signatureAlgorithm,
|
|
1031
|
-
key,
|
|
1032
|
-
encoder2.encode(canonicalizeJson(omitSignature(value)))
|
|
1033
|
-
);
|
|
1034
|
-
return { ...omitSignature(value), signature: encodeWorkspaceBytes2(new Uint8Array(signature)) };
|
|
1035
|
-
}
|
|
1036
|
-
async function verifyWorkspaceSignature2(value, publicKey) {
|
|
1037
|
-
try {
|
|
1038
|
-
const key = await crypto.subtle.importKey("jwk", publicKey, ec, false, ["verify"]);
|
|
1039
|
-
return await crypto.subtle.verify(
|
|
1040
|
-
signatureAlgorithm,
|
|
1041
|
-
key,
|
|
1042
|
-
decodeWorkspaceBytes2(value.signature),
|
|
1043
|
-
encoder2.encode(canonicalizeJson(omitSignature(value)))
|
|
1044
|
-
);
|
|
1045
|
-
} catch {
|
|
1046
|
-
return false;
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
async function seal(value, rawKey, context, limit = maxBytes) {
|
|
1050
|
-
const bytes = encoder2.encode(canonicalizeJson(value));
|
|
1051
|
-
if (bytes.length + 16 > limit)
|
|
1052
|
-
throw Object.assign(
|
|
1053
|
-
new RangeError(
|
|
1054
|
-
`Encrypted ${label.toLowerCase()} data exceeds the ${Math.floor(limit / 1024)} KB upload limit.`
|
|
1055
|
-
),
|
|
1056
|
-
{ code: "E_WORKSPACE_PAYLOAD_TOO_LARGE", status: 413 }
|
|
1057
|
-
);
|
|
1058
|
-
const key = await crypto.subtle.importKey("raw", rawKey, "AES-GCM", false, ["encrypt"]);
|
|
1059
|
-
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
1060
|
-
const ciphertext = await crypto.subtle.encrypt(
|
|
1061
|
-
{ name: "AES-GCM", iv, additionalData: encoder2.encode(canonicalizeJson(context)) },
|
|
1062
|
-
key,
|
|
1063
|
-
bytes
|
|
1064
|
-
);
|
|
1065
|
-
return {
|
|
1066
|
-
iv: encodeWorkspaceBytes2(iv),
|
|
1067
|
-
ciphertext: encodeWorkspaceBytes2(new Uint8Array(ciphertext))
|
|
1068
|
-
};
|
|
1069
|
-
}
|
|
1070
|
-
async function unseal(value, rawKey, context, limit = maxBytes) {
|
|
1071
|
-
const bytes = decodeWorkspaceBytes2(value.ciphertext);
|
|
1072
|
-
if (bytes.length > limit)
|
|
1073
|
-
throw new RangeError(`Shared ${label.toLowerCase()} data exceeds its size limit.`);
|
|
1074
|
-
const key = await crypto.subtle.importKey("raw", rawKey, "AES-GCM", false, ["decrypt"]);
|
|
1075
|
-
const plaintext = await crypto.subtle.decrypt(
|
|
1076
|
-
{
|
|
1077
|
-
name: "AES-GCM",
|
|
1078
|
-
iv: decodeWorkspaceBytes2(value.iv),
|
|
1079
|
-
additionalData: encoder2.encode(canonicalizeJson(context))
|
|
1080
|
-
},
|
|
1081
|
-
key,
|
|
1082
|
-
bytes
|
|
1083
|
-
);
|
|
1084
|
-
return JSON.parse(decoder2.decode(plaintext));
|
|
1085
|
-
}
|
|
1086
|
-
const keyringContext = (id, epoch) => ({ type: "keyring", workspaceId: id, epoch });
|
|
1087
|
-
const revisionContext = (id, revision) => ({
|
|
1088
|
-
type: "revision",
|
|
1089
|
-
workspaceId: id,
|
|
1090
|
-
id: revision.id,
|
|
1091
|
-
epoch: revision.epoch,
|
|
1092
|
-
reviewOf: revision.reviewOf
|
|
1093
|
-
});
|
|
1094
|
-
const eventContext = (id, event) => ({
|
|
1095
|
-
type: "event",
|
|
1096
|
-
workspaceId: id,
|
|
1097
|
-
id: event.id,
|
|
1098
|
-
epoch: event.epoch,
|
|
1099
|
-
revisionId: event.revisionId,
|
|
1100
|
-
reviewOf: event.reviewOf
|
|
1101
|
-
});
|
|
1102
|
-
function workspaceEnvelopeDigest2(value) {
|
|
1103
|
-
return bundleDigest(value);
|
|
1104
|
-
}
|
|
1105
|
-
async function wrapKeyring(custody, token = custody.token, epoch = custody.epoch, keys = custody.keys) {
|
|
1106
|
-
return seal(
|
|
1107
|
-
{ keys, ownerPublicKey: custody.ownerPublicKey },
|
|
1108
|
-
await tokenMaterial(token, custody.id, "key-wrap"),
|
|
1109
|
-
keyringContext(custody.id, epoch)
|
|
1110
|
-
);
|
|
1111
|
-
}
|
|
1112
|
-
async function prepareRevision(custody, bundle) {
|
|
1113
|
-
assertBundle(bundle);
|
|
1114
|
-
const header = {
|
|
1115
|
-
id: newWorkspaceId2(),
|
|
1116
|
-
epoch: custody.epoch,
|
|
1117
|
-
reviewOf: workspaceEnvelopeDigest2(digestInput(bundle)),
|
|
1118
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1119
|
-
};
|
|
1120
|
-
return signWorkspaceValue2(
|
|
1121
|
-
{
|
|
1122
|
-
...header,
|
|
1123
|
-
...await seal(
|
|
1124
|
-
await packBundle(bundle),
|
|
1125
|
-
decodeWorkspaceBytes2(custody.keys[custody.epoch]),
|
|
1126
|
-
revisionContext(custody.id, header)
|
|
1127
|
-
)
|
|
1128
|
-
},
|
|
1129
|
-
custody.ownerPrivateKey
|
|
1130
|
-
);
|
|
1131
|
-
}
|
|
1132
|
-
async function prepareWorkspace2(bundle, { baseUrl = defaultBaseUrl } = {}) {
|
|
1133
|
-
const signer = await createWorkspaceSigner2();
|
|
1134
|
-
const custody = {
|
|
1135
|
-
schemaVersion: version,
|
|
1136
|
-
id: newWorkspaceId2(),
|
|
1137
|
-
baseUrl: normalizeWorkspaceBase2(baseUrl),
|
|
1138
|
-
token: newWorkspaceToken2(),
|
|
1139
|
-
ownerAuth: newWorkspaceToken2(),
|
|
1140
|
-
ownerPrivateKey: signer.privateKey,
|
|
1141
|
-
ownerPublicKey: signer.publicKey,
|
|
1142
|
-
epoch: 1,
|
|
1143
|
-
keys: { 1: newWorkspaceToken2() },
|
|
1144
|
-
version: 0
|
|
1145
|
-
};
|
|
1146
|
-
custody.keyring = await wrapKeyring(custody);
|
|
1147
|
-
custody.pendingCreate = await signWorkspaceValue2(
|
|
1148
|
-
{
|
|
1149
|
-
schemaVersion: version,
|
|
1150
|
-
id: custody.id,
|
|
1151
|
-
ownerPublicKey: custody.ownerPublicKey,
|
|
1152
|
-
ownerAuthHash: sha256Hex(custody.ownerAuth),
|
|
1153
|
-
reviewerAuthHash: sha256Hex(await deriveWorkspaceAuthentication2(custody.token, custody.id)),
|
|
1154
|
-
epoch: 1,
|
|
1155
|
-
keyring: custody.keyring,
|
|
1156
|
-
revision: await prepareRevision(custody, bundle),
|
|
1157
|
-
operationId: newWorkspaceId2()
|
|
1158
|
-
},
|
|
1159
|
-
custody.ownerPrivateKey
|
|
1160
|
-
);
|
|
1161
|
-
assertContract(custody.pendingCreate, schemas.create);
|
|
1162
|
-
return custody;
|
|
1163
|
-
}
|
|
1164
|
-
async function request(access, suffix = "", {
|
|
1165
|
-
method = "GET",
|
|
1166
|
-
body,
|
|
1167
|
-
fetchImpl = globalThis.fetch,
|
|
1168
|
-
owner = Boolean(access.ownerAuth),
|
|
1169
|
-
timeoutMs = 2e4
|
|
1170
|
-
} = {}) {
|
|
1171
|
-
if (!idPattern.test(access.id))
|
|
1172
|
-
throw new TypeError(`Invalid ${label.toLowerCase()} workspace identity.`);
|
|
1173
|
-
const authorization = owner ? access.ownerAuth : await deriveWorkspaceAuthentication2(access.token, access.id);
|
|
1174
|
-
const headers = { Authorization: `Bearer ${authorization}`, Accept: "application/json" };
|
|
1175
|
-
if (body) headers["Content-Type"] = "application/json";
|
|
1176
|
-
let response;
|
|
1177
|
-
try {
|
|
1178
|
-
response = await fetchImpl(
|
|
1179
|
-
`${normalizeWorkspaceBase2(access.baseUrl)}${apiPath}/${access.id}${suffix}`,
|
|
1180
|
-
{
|
|
1181
|
-
method,
|
|
1182
|
-
headers,
|
|
1183
|
-
body: body ? JSON.stringify(body) : void 0,
|
|
1184
|
-
redirect: "error",
|
|
1185
|
-
cache: "no-store",
|
|
1186
|
-
credentials: "omit",
|
|
1187
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
1188
|
-
}
|
|
1189
|
-
);
|
|
1190
|
-
} catch {
|
|
1191
|
-
throw operationError(
|
|
1192
|
-
`${label} sharing is unreachable. Check the connection and retry; the previous review is unchanged.`,
|
|
1193
|
-
"E_WORKSPACE_NETWORK"
|
|
1194
|
-
);
|
|
1195
|
-
}
|
|
1196
|
-
if (!response.ok) await throwResponseError(response, method);
|
|
1197
|
-
return readResponse(response);
|
|
1198
|
-
}
|
|
1199
|
-
async function throwResponseError(response, method) {
|
|
1200
|
-
if (response.status === 404 && method === "PUT" && compatibilityMessage) {
|
|
1201
|
-
const error2 = new Error(compatibilityMessage);
|
|
1202
|
-
error2.code = compatibilityCode;
|
|
1203
|
-
error2.status = 404;
|
|
1204
|
-
throw error2;
|
|
1205
|
-
}
|
|
1206
|
-
const messages = {
|
|
1207
|
-
401: "Access token is incorrect or has been rotated.",
|
|
1208
|
-
403: "This review is unavailable or this action requires its owner.",
|
|
1209
|
-
404: "This shared review could not be found.",
|
|
1210
|
-
409: "The shared review changed. Refresh its status before retrying.",
|
|
1211
|
-
410: "This shared review has been revoked or deleted.",
|
|
1212
|
-
413: `This ${label.toLowerCase()} exceeds the sharing upload limit.`,
|
|
1213
|
-
429: "Too many requests. Wait a moment and retry.",
|
|
1214
|
-
503: `${label} sharing is temporarily unavailable. Retry shortly.`
|
|
1215
|
-
};
|
|
1216
|
-
const error = new Error(
|
|
1217
|
-
messages[response.status] ?? `${label} sharing failed (${response.status}). Retry shortly.`
|
|
1218
|
-
);
|
|
1219
|
-
error.status = response.status;
|
|
1220
|
-
error.code = `E_WORKSPACE_HTTP_${response.status}`;
|
|
1221
|
-
try {
|
|
1222
|
-
const reader = response.body?.getReader();
|
|
1223
|
-
const body = reader && JSON.parse(decoder2.decode(await responseBytes(reader, 4096)));
|
|
1224
|
-
if (typeof body?.error === "string" && /^[A-Za-z][A-Za-z0-9_-]{0,127}$/u.test(body.error))
|
|
1225
|
-
error.code = body.error;
|
|
1226
|
-
} catch {
|
|
1227
|
-
}
|
|
1228
|
-
if (response.status === 429) {
|
|
1229
|
-
const header = response.headers.get("retry-after");
|
|
1230
|
-
const seconds = header && /^\d+(?:\.\d+)?$/u.test(header.trim()) ? Number(header) : header ? (Date.parse(header) - Date.now()) / 1e3 : NaN;
|
|
1231
|
-
if (Number.isFinite(seconds) && seconds >= 0)
|
|
1232
|
-
error.retryAfterSeconds = Math.min(3600, Math.max(1, Math.ceil(seconds)));
|
|
1233
|
-
}
|
|
1234
|
-
throw error;
|
|
1235
|
-
}
|
|
1236
|
-
async function responseBytes(reader, limit) {
|
|
1237
|
-
const chunks = [];
|
|
1238
|
-
let length = 0;
|
|
1239
|
-
try {
|
|
1240
|
-
for (; ; ) {
|
|
1241
|
-
const { value, done } = await reader.read();
|
|
1242
|
-
if (done) break;
|
|
1243
|
-
length += value.length;
|
|
1244
|
-
if (length > limit) {
|
|
1245
|
-
await reader.cancel();
|
|
1246
|
-
throw new RangeError(`${label} service returned an oversized response.`);
|
|
1247
|
-
}
|
|
1248
|
-
chunks.push(value);
|
|
1249
|
-
}
|
|
1250
|
-
} catch (error) {
|
|
1251
|
-
if (error instanceof RangeError) throw error;
|
|
1252
|
-
throw new Error("The sharing response was interrupted. Retry the pending operation.");
|
|
1253
|
-
}
|
|
1254
|
-
const bytes = new Uint8Array(length);
|
|
1255
|
-
let offset = 0;
|
|
1256
|
-
for (const chunk of chunks) {
|
|
1257
|
-
bytes.set(chunk, offset);
|
|
1258
|
-
offset += chunk.length;
|
|
1259
|
-
}
|
|
1260
|
-
return bytes;
|
|
1261
|
-
}
|
|
1262
|
-
async function readResponse(response) {
|
|
1263
|
-
if (response.status === 204) return {};
|
|
1264
|
-
const reader = response.body?.getReader();
|
|
1265
|
-
if (!reader) throw new Error(`${label} service returned an empty response.`);
|
|
1266
|
-
try {
|
|
1267
|
-
return JSON.parse(decoder2.decode(await responseBytes(reader, maxBytes * 1.5 + 65536)));
|
|
1268
|
-
} catch (cause) {
|
|
1269
|
-
throw Object.assign(
|
|
1270
|
-
operationError(
|
|
1271
|
-
"The sharing response could not be verified. Retry the pending operation.",
|
|
1272
|
-
"E_WORKSPACE_RESPONSE_INVALID"
|
|
1273
|
-
),
|
|
1274
|
-
{ cause }
|
|
1275
|
-
);
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
async function commitWorkspace2(custody, options = {}) {
|
|
1279
|
-
if (!custody.pendingCreate) return getWorkspace2(custody, options);
|
|
1280
|
-
const result = await request(custody, "", {
|
|
1281
|
-
...options,
|
|
1282
|
-
method: "PUT",
|
|
1283
|
-
body: custody.pendingCreate
|
|
1284
|
-
});
|
|
1285
|
-
assertContract(result, schemas.workspace);
|
|
1286
|
-
if (result.id !== custody.id || result.version !== 1 || result.epoch !== 1 || result.currentRevision !== custody.pendingCreate.revision.id || canonicalizeJson(result.ownerPublicKey) !== canonicalizeJson(custody.ownerPublicKey) || canonicalizeJson(result.keyring) !== canonicalizeJson(custody.keyring))
|
|
1287
|
-
throw new Error("The sharing creation receipt is invalid. Retry the saved operation.");
|
|
1288
|
-
custody.version = result.version;
|
|
1289
|
-
custody.currentRevision = result.currentRevision;
|
|
1290
|
-
delete custody.pendingCreate;
|
|
1291
|
-
return result;
|
|
1292
|
-
}
|
|
1293
|
-
async function getWorkspace2(access, options = {}) {
|
|
1294
|
-
const result = assertContract(await request(access, "", options), schemas.workspace);
|
|
1295
|
-
if (result.id !== access.id) throw new Error("Shared review identity mismatch.");
|
|
1296
|
-
const ring = await unseal(
|
|
1297
|
-
result.keyring,
|
|
1298
|
-
await tokenMaterial(access.token, access.id, "key-wrap"),
|
|
1299
|
-
keyringContext(access.id, result.epoch)
|
|
1300
|
-
);
|
|
1301
|
-
if (canonicalizeJson(ring.ownerPublicKey) !== canonicalizeJson(result.ownerPublicKey) || access.ownerPublicKey && canonicalizeJson(access.ownerPublicKey) !== canonicalizeJson(result.ownerPublicKey))
|
|
1302
|
-
throw new Error("Shared review owner identity changed.");
|
|
1303
|
-
if (!ring.keys?.[result.epoch] || Object.entries(ring.keys).some(
|
|
1304
|
-
([keyEpoch, key]) => !/^[1-9][0-9]*$/u.test(keyEpoch) || !tokenPattern.test(key)
|
|
1305
|
-
))
|
|
1306
|
-
throw new Error("Invalid shared review key history.");
|
|
1307
|
-
Object.assign(access, {
|
|
1308
|
-
keys: ring.keys,
|
|
1309
|
-
ownerPublicKey: result.ownerPublicKey,
|
|
1310
|
-
epoch: result.epoch,
|
|
1311
|
-
keyring: result.keyring,
|
|
1312
|
-
version: result.version,
|
|
1313
|
-
currentRevision: result.currentRevision,
|
|
1314
|
-
commentsPaused: result.commentsPaused
|
|
1315
|
-
});
|
|
1316
|
-
return result;
|
|
1317
|
-
}
|
|
1318
|
-
async function listWorkspaceRevisions(access, { after = "", ...options } = {}) {
|
|
1319
|
-
if (after && !idPattern.test(after)) throw new TypeError("Invalid revision cursor.");
|
|
1320
|
-
return request(
|
|
1321
|
-
access,
|
|
1322
|
-
`/revisions${after ? `?after=${encodeURIComponent(after)}` : ""}`,
|
|
1323
|
-
options
|
|
1324
|
-
);
|
|
1325
|
-
}
|
|
1326
|
-
async function decryptWorkspaceRevision2(access, revisionId = access.currentRevision, options = {}) {
|
|
1327
|
-
if (!access.keys) await getWorkspace2(access, options);
|
|
1328
|
-
if (!idPattern.test(revisionId))
|
|
1329
|
-
throw new TypeError(`Invalid ${label.toLowerCase()} revision.`);
|
|
1330
|
-
const revision = assertContract(
|
|
1331
|
-
await request(access, `/revisions/${revisionId}`, options),
|
|
1332
|
-
schemas.revision
|
|
1333
|
-
);
|
|
1334
|
-
if (revision.id !== revisionId || !await verifyWorkspaceSignature2(revision, access.ownerPublicKey))
|
|
1335
|
-
throw new Error(`The published ${label.toLowerCase()} signature is invalid.`);
|
|
1336
|
-
if (!access.keys[revision.epoch])
|
|
1337
|
-
throw new Error("The access token cannot open this revision.");
|
|
1338
|
-
const bundle = assertBundle(
|
|
1339
|
-
await unpackBundle(
|
|
1340
|
-
await unseal(
|
|
1341
|
-
revision,
|
|
1342
|
-
decodeWorkspaceBytes2(access.keys[revision.epoch]),
|
|
1343
|
-
revisionContext(access.id, revision)
|
|
1344
|
-
)
|
|
1345
|
-
)
|
|
1346
|
-
);
|
|
1347
|
-
if (workspaceEnvelopeDigest2(digestInput(bundle)) !== revision.reviewOf)
|
|
1348
|
-
throw new Error(`Published ${label.toLowerCase()} content does not match its revision.`);
|
|
1349
|
-
return { ...bundle, workspaceRevision: revision.id, reviewOf: revision.reviewOf };
|
|
1350
|
-
}
|
|
1351
|
-
async function prepareWorkspaceMutation2(custody, action, payload = void 0) {
|
|
1352
|
-
if (custody.pendingCreate)
|
|
1353
|
-
throw new Error("Finish creating this shared review before changing it.");
|
|
1354
|
-
if (custody.pendingMutation)
|
|
1355
|
-
throw new Error("A sharing operation is pending. Retry it before making another change.");
|
|
1356
|
-
const body = {
|
|
1357
|
-
operationId: newWorkspaceId2(),
|
|
1358
|
-
expectedVersion: custody.version,
|
|
1359
|
-
epoch: custody.epoch
|
|
1360
|
-
};
|
|
1361
|
-
let next = {};
|
|
1362
|
-
if (action === "publish") body.revision = await prepareRevision(custody, payload);
|
|
1363
|
-
else if (action === "rotate") {
|
|
1364
|
-
const token = newWorkspaceToken2();
|
|
1365
|
-
const epoch = custody.epoch + 1;
|
|
1366
|
-
const keys = { ...custody.keys, [epoch]: newWorkspaceToken2() };
|
|
1367
|
-
const keyring = await wrapKeyring(custody, token, epoch, keys);
|
|
1368
|
-
Object.assign(body, {
|
|
1369
|
-
epoch,
|
|
1370
|
-
reviewerAuthHash: sha256Hex(await deriveWorkspaceAuthentication2(token, custody.id)),
|
|
1371
|
-
keyring
|
|
1372
|
-
});
|
|
1373
|
-
next = { token, epoch, keys, keyring };
|
|
1374
|
-
} else if (["pause", "resume", "revoke", "delete"].includes(action)) body.action = action;
|
|
1375
|
-
else throw new TypeError(`Unknown ${label.toLowerCase()} sharing operation.`);
|
|
1376
|
-
custody.pendingMutation = {
|
|
1377
|
-
action,
|
|
1378
|
-
body: await signWorkspaceValue2(body, custody.ownerPrivateKey),
|
|
1379
|
-
next
|
|
1380
|
-
};
|
|
1381
|
-
return custody.pendingMutation;
|
|
1382
|
-
}
|
|
1383
|
-
function assertDeletionReceipt(custody, result) {
|
|
1384
|
-
if (result.schemaVersion !== version || result.id !== custody.id || result.deleted !== true || Object.keys(result).some((key) => !["schemaVersion", "id", "deleted"].includes(key)))
|
|
1385
|
-
throw new Error("The deletion receipt is invalid. Retry the saved operation.");
|
|
1386
|
-
}
|
|
1387
|
-
function assertMutationReceipt(custody, pending, result) {
|
|
1388
|
-
if (pending.action === "delete") return assertDeletionReceipt(custody, result);
|
|
1389
|
-
assertContract(result, schemas.workspace);
|
|
1390
|
-
const expectedRevision = pending.action === "publish" ? pending.body.revision.id : custody.currentRevision;
|
|
1391
|
-
if (result.id !== custody.id || result.version !== pending.body.expectedVersion + 1 || result.epoch !== pending.body.epoch || result.currentRevision !== expectedRevision || canonicalizeJson(result.ownerPublicKey) !== canonicalizeJson(custody.ownerPublicKey) || canonicalizeJson(result.keyring) !== canonicalizeJson(pending.next.keyring ?? custody.keyring) || ["pause", "resume"].includes(pending.action) && result.commentsPaused !== (pending.action === "pause"))
|
|
1392
|
-
throw new Error("The sharing operation receipt is invalid. Retry the saved operation.");
|
|
1393
|
-
}
|
|
1394
|
-
async function commitWorkspaceMutation2(custody, options = {}) {
|
|
1395
|
-
const pending = custody.pendingMutation;
|
|
1396
|
-
if (!pending) throw new Error("No sharing operation is pending.");
|
|
1397
|
-
const suffix = ["publish", "rotate"].includes(pending.action) ? pending.action : "manage";
|
|
1398
|
-
const result = await request(custody, `/${suffix}`, {
|
|
1399
|
-
...options,
|
|
1400
|
-
method: "POST",
|
|
1401
|
-
body: pending.body
|
|
1402
|
-
});
|
|
1403
|
-
assertMutationReceipt(custody, pending, result);
|
|
1404
|
-
Object.assign(custody, pending.next, { version: pending.body.expectedVersion + 1 });
|
|
1405
|
-
if (pending.action === "publish") custody.currentRevision = pending.body.revision.id;
|
|
1406
|
-
if (pending.action === "pause" || pending.action === "resume")
|
|
1407
|
-
custody.commentsPaused = pending.action === "pause";
|
|
1408
|
-
if (pending.action === "revoke" || pending.action === "delete")
|
|
1409
|
-
custody.status = pending.action === "revoke" ? "revoked" : "deleted";
|
|
1410
|
-
delete custody.pendingMutation;
|
|
1411
|
-
return result;
|
|
1412
|
-
}
|
|
1413
|
-
async function publishWorkspace(custody, bundle, options = {}) {
|
|
1414
|
-
await prepareWorkspaceMutation2(custody, "publish", bundle);
|
|
1415
|
-
return commitWorkspaceMutation2(custody, options);
|
|
1416
|
-
}
|
|
1417
|
-
async function rotateWorkspace(custody, options = {}) {
|
|
1418
|
-
await prepareWorkspaceMutation2(custody, "rotate");
|
|
1419
|
-
return commitWorkspaceMutation2(custody, options);
|
|
1420
|
-
}
|
|
1421
|
-
async function manageWorkspace(custody, action, options = {}) {
|
|
1422
|
-
await prepareWorkspaceMutation2(custody, action);
|
|
1423
|
-
return commitWorkspaceMutation2(custody, options);
|
|
1424
|
-
}
|
|
1425
|
-
async function prepareWorkspaceEvent2(access, payload, { revisionId = access.currentRevision, reviewOf = payload.reviewOf, signer } = {}) {
|
|
1426
|
-
if (!access.keys) throw new Error("Unlock the shared review before commenting.");
|
|
1427
|
-
assertFeedback(payload);
|
|
1428
|
-
const identity = signer ?? await createWorkspaceSigner2();
|
|
1429
|
-
const publicKey = canonicalWorkspacePublicKey2(identity.publicKey);
|
|
1430
|
-
const header = { id: newWorkspaceId2(), revisionId, reviewOf, epoch: access.epoch };
|
|
1431
|
-
const event = await signWorkspaceValue2(
|
|
1432
|
-
{
|
|
1433
|
-
...header,
|
|
1434
|
-
...await seal(
|
|
1435
|
-
payload,
|
|
1436
|
-
decodeWorkspaceBytes2(access.keys[access.epoch]),
|
|
1437
|
-
eventContext(access.id, header),
|
|
1438
|
-
maxEventBytes
|
|
1439
|
-
),
|
|
1440
|
-
publicKey
|
|
1441
|
-
},
|
|
1442
|
-
identity.privateKey
|
|
1443
|
-
);
|
|
1444
|
-
return assertContract(event, schemas.event);
|
|
1445
|
-
}
|
|
1446
|
-
async function appendWorkspaceEvent2(access, payload, { preparedEvent, signer, revisionId, reviewOf, ...options } = {}) {
|
|
1447
|
-
const event = preparedEvent ?? await prepareWorkspaceEvent2(access, payload, {
|
|
1448
|
-
signer,
|
|
1449
|
-
revisionId,
|
|
1450
|
-
reviewOf: reviewOf ?? payload.reviewOf
|
|
1451
|
-
});
|
|
1452
|
-
const result = await request(access, "/events", { ...options, method: "POST", body: event });
|
|
1453
|
-
if (!result || typeof result !== "object" || Array.isArray(result) || !Number.isSafeInteger(result.sequence) || result.sequence < 1 || !result.event || typeof result.event !== "object" || Array.isArray(result.event))
|
|
1454
|
-
throw new Error("The feedback receipt is invalid. Retry the saved operation.");
|
|
1455
|
-
const { sequence: eventSequence, ...received } = result.event;
|
|
1456
|
-
if (eventSequence !== void 0 && eventSequence !== result.sequence || canonicalizeJson(received) !== canonicalizeJson(event))
|
|
1457
|
-
throw new Error(
|
|
1458
|
-
"The feedback receipt does not match the saved event. Retry the saved operation."
|
|
1459
|
-
);
|
|
1460
|
-
return { event: { ...received, sequence: result.sequence }, sequence: result.sequence };
|
|
1461
|
-
}
|
|
1462
|
-
function assertEventPage(page, after) {
|
|
1463
|
-
if (!Array.isArray(page.events) || page.events.length > 100 || !Number.isSafeInteger(page.cursor) || page.cursor < after || typeof page.hasMore !== "boolean")
|
|
1464
|
-
throw new Error("Invalid shared feedback page.");
|
|
1465
|
-
}
|
|
1466
|
-
async function decryptEvent(access, record, sequence) {
|
|
1467
|
-
assertContract(record, schemas.event);
|
|
1468
|
-
if (!await verifyWorkspaceSignature2(record, record.publicKey))
|
|
1469
|
-
throw new Error("Signature verification failed.");
|
|
1470
|
-
if (!access.keys[record.epoch]) throw new Error("The encryption epoch is unavailable.");
|
|
1471
|
-
const payload = await unseal(
|
|
1472
|
-
record,
|
|
1473
|
-
decodeWorkspaceBytes2(access.keys[record.epoch]),
|
|
1474
|
-
eventContext(access.id, record),
|
|
1475
|
-
maxEventBytes
|
|
1476
|
-
);
|
|
1477
|
-
assertFeedback(payload);
|
|
1478
|
-
if (payload.reviewOf !== record.reviewOf) throw new Error("Feedback revision is invalid.");
|
|
1479
|
-
return { ...record, sequence, payload };
|
|
1480
|
-
}
|
|
1481
|
-
function eventFromPage(item, pageIds, previousSequence, cursor) {
|
|
1482
|
-
const { sequence, ...record } = item?.event ? { ...item.event, sequence: item.sequence } : item ?? {};
|
|
1483
|
-
if (!Number.isSafeInteger(sequence) || sequence <= previousSequence || sequence > cursor)
|
|
1484
|
-
throw new Error("Invalid shared feedback sequence.");
|
|
1485
|
-
if (typeof record.id !== "string" || pageIds.has(record.id))
|
|
1486
|
-
throw new Error("Invalid shared feedback event identity.");
|
|
1487
|
-
pageIds.add(record.id);
|
|
1488
|
-
return { sequence, record };
|
|
1489
|
-
}
|
|
1490
|
-
async function readWorkspaceEvents2(access, { after = 0, ...options } = {}) {
|
|
1491
|
-
if (!Number.isSafeInteger(after) || after < 0) throw new TypeError("Invalid feedback cursor.");
|
|
1492
|
-
if (!access.keys) await getWorkspace2(access, options);
|
|
1493
|
-
const page = await request(access, `/events?after=${after}`, options);
|
|
1494
|
-
assertEventPage(page, after);
|
|
1495
|
-
const events = [], issues = [], pageIds = /* @__PURE__ */ new Set();
|
|
1496
|
-
let previousSequence = after;
|
|
1497
|
-
for (const item of page.events) {
|
|
1498
|
-
const { sequence, record } = eventFromPage(item, pageIds, previousSequence, page.cursor);
|
|
1499
|
-
previousSequence = sequence;
|
|
1500
|
-
try {
|
|
1501
|
-
events.push(await decryptEvent(access, record, sequence));
|
|
1502
|
-
} catch {
|
|
1503
|
-
issues.push({
|
|
1504
|
-
sequence,
|
|
1505
|
-
id: typeof record.id === "string" && idPattern.test(record.id) ? record.id : null,
|
|
1506
|
-
reason: "Invalid encrypted feedback; not imported."
|
|
1507
|
-
});
|
|
1508
|
-
}
|
|
1509
|
-
}
|
|
1510
|
-
return { ...page, events, issues };
|
|
1511
|
-
}
|
|
1512
|
-
return {
|
|
1513
|
-
encodeWorkspaceBytes: encodeWorkspaceBytes2,
|
|
1514
|
-
decodeWorkspaceBytes: decodeWorkspaceBytes2,
|
|
1515
|
-
newWorkspaceToken: newWorkspaceToken2,
|
|
1516
|
-
newWorkspaceId: newWorkspaceId2,
|
|
1517
|
-
normalizeWorkspaceBase: normalizeWorkspaceBase2,
|
|
1518
|
-
workspaceReviewUrl: workspaceReviewUrl2,
|
|
1519
|
-
deriveWorkspaceAuthentication: deriveWorkspaceAuthentication2,
|
|
1520
|
-
canonicalWorkspacePublicKey: canonicalWorkspacePublicKey2,
|
|
1521
|
-
createWorkspaceSigner: createWorkspaceSigner2,
|
|
1522
|
-
signWorkspaceValue: signWorkspaceValue2,
|
|
1523
|
-
verifyWorkspaceSignature: verifyWorkspaceSignature2,
|
|
1524
|
-
workspaceEnvelopeDigest: workspaceEnvelopeDigest2,
|
|
1525
|
-
prepareWorkspace: prepareWorkspace2,
|
|
1526
|
-
commitWorkspace: commitWorkspace2,
|
|
1527
|
-
getWorkspace: getWorkspace2,
|
|
1528
|
-
listWorkspaceRevisions,
|
|
1529
|
-
decryptWorkspaceRevision: decryptWorkspaceRevision2,
|
|
1530
|
-
prepareWorkspaceMutation: prepareWorkspaceMutation2,
|
|
1531
|
-
commitWorkspaceMutation: commitWorkspaceMutation2,
|
|
1532
|
-
publishWorkspace,
|
|
1533
|
-
rotateWorkspace,
|
|
1534
|
-
manageWorkspace,
|
|
1535
|
-
prepareWorkspaceEvent: prepareWorkspaceEvent2,
|
|
1536
|
-
appendWorkspaceEvent: appendWorkspaceEvent2,
|
|
1537
|
-
readWorkspaceEvents: readWorkspaceEvents2
|
|
1538
|
-
};
|
|
1539
|
-
}
|
|
1540
|
-
|
|
1541
915
|
// packages/design/lib/design/workspace-client.mjs
|
|
1542
916
|
var encoder = new TextEncoder();
|
|
1543
917
|
var decoder = new TextDecoder("utf-8", { fatal: true });
|
|
@@ -2425,7 +1799,7 @@ async function importDesignShareRecovery(file, { input, ...options } = {}) {
|
|
|
2425
1799
|
const pending = custody.pendingCreate ?? custody.pendingMutation.body;
|
|
2426
1800
|
const destination = join3(root, "uploads", custody.id, pending.operationId);
|
|
2427
1801
|
if (existsSync4(destination)) {
|
|
2428
|
-
const { spoolChunkReader: spoolChunkReader2 } = await import("./design-
|
|
1802
|
+
const { spoolChunkReader: spoolChunkReader2 } = await import("./design-runtime-support-5cb7531bede8.mjs");
|
|
2429
1803
|
const reader = spoolChunkReader2(destination, pending);
|
|
2430
1804
|
for (const part of pending.manifest.chunks) await reader(part.index);
|
|
2431
1805
|
} else await copyUploadSpool(custody, destination);
|
|
@@ -2601,7 +1975,6 @@ export {
|
|
|
2601
1975
|
resolveArtifactReviewDestination,
|
|
2602
1976
|
decodeArtifactReviewSources,
|
|
2603
1977
|
getDesignShareStatus,
|
|
2604
|
-
prepareDesignShareBundle,
|
|
2605
1978
|
shareDesign,
|
|
2606
1979
|
publishDesignShare,
|
|
2607
1980
|
manageDesignShare,
|