@kieransimkin/dancemoves 3.1.22 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/docs/api/surface.json +10 -0
- package/docs/api/wordpress.md +68 -22
- package/docs/audio-recording-playback.md +56 -0
- package/lib/build-manifest.json +11 -11
- package/lib/dancemoves.min.js +3 -3
- package/lib/index.cjs +242 -63
- package/lib/index.d.ts +5 -1
- package/lib/index.mjs +242 -63
- package/lib/wordpress.js +3 -3
- package/package.json +1 -1
- package/readme.txt +12 -3
package/README.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# DanceMoves
|
|
2
2
|
|
|
3
|
+
**3.2.0** adds native, non-looping playback of StemLab/DanceRudiments audio-derived movement recordings. `runtime.recordings` composes the existing audio clock, shared player mapping, accessibility preferences and lifecycle. Captured BPM must match page metadata; samples retain their original integer-pip clock and never wrap. See [recording playback](docs/audio-recording-playback.md).
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
**3.1.23** secures WordPress motion-capture writes with authenticated
|
|
7
|
+
`manage_options` authorization. The private capture administration UI uses the
|
|
8
|
+
same capability. Published tokens no longer authorize uploads; cookie clients
|
|
9
|
+
send a fresh WordPress REST nonce and same-origin credentials, and administrators
|
|
10
|
+
have separate bounded upload quotas. Local recording/download stays available
|
|
11
|
+
without upload authorization. See the [capture contract](docs/api/wordpress.md#motion-capture-rest-api).
|
|
12
|
+
The real WordPress integration test reports its executed assertion count;
|
|
13
|
+
CI rejects a missing or zero-count summary as well as any failed check.
|
|
14
|
+
|
|
3
15
|
**3.1.22** fixes WordPress.org submission metadata: the Author URI points to
|
|
4
16
|
[Kieran's website](https://kieransimkin.co.uk/), separately from the plugin
|
|
5
17
|
homepage. The release checker rejects duplicate plugin/author URLs before
|
|
@@ -602,7 +614,8 @@ const example = {schema:'ks-epk-motion-recording/v1', samples:[{t:0,beta:10,gamm
|
|
|
602
614
|
inspect(example);
|
|
603
615
|
// The local simulator uses /examples/wordpress/api/capture, never /wp-json/… .
|
|
604
616
|
// For actual captures, follow docs/api/wordpress.md and the private sensor harness.
|
|
605
|
-
//
|
|
617
|
+
// Uploads require administrator authorization and a fresh WordPress REST nonce.
|
|
618
|
+
// Keep real session nonces out of static examples and source control.
|
|
606
619
|
```
|
|
607
620
|
|
|
608
621
|
[Run the example](examples/wordpress/capture.html) · [Read its complete source](examples/wordpress/demos/capture.mjs).
|
package/docs/api/surface.json
CHANGED
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
"effects_version": "3.1.13",
|
|
8
8
|
"effects_reviewed_on": "2026-10-08",
|
|
9
9
|
"inventory_method": "Manual comparison with the pinned source exports and PHP declarations; symbol-presence validation is not runtime coverage.",
|
|
10
|
+
"wordpress_capture_security": {
|
|
11
|
+
"version": "3.1.23",
|
|
12
|
+
"reviewed_on": "2026-10-15",
|
|
13
|
+
"scope": "Current capture contract supersedes the historical 2.8.0 capture authorization, quota and post-type capability description; pinned baseline symbols and source hashes below remain historical evidence.",
|
|
14
|
+
"authorization": "WordPress-authenticated current_user_can('manage_options'); cookie REST nonces are checked by WordPress core",
|
|
15
|
+
"removed_constants": ["KS_EPK_MOTION_CAPTURE_TOKEN"],
|
|
16
|
+
"quota": "ks_motion_user_<authenticated user ID>, eight accepted checks per ten-minute expiry",
|
|
17
|
+
"private_capture_capability": "manage_options",
|
|
18
|
+
"reference": "wordpress.md#motion-capture-rest-api"
|
|
19
|
+
},
|
|
10
20
|
"source_blobs": {
|
|
11
21
|
"kieran-epk-device-orientation.php": "b374690a0c141aa1f870bf1084a0a0b34c25abe5",
|
|
12
22
|
"assets/dance-moves-core.js": "3d975c7a3b380f9c99a62f7deade14df4b746929",
|
package/docs/api/wordpress.md
CHANGED
|
@@ -15,7 +15,7 @@ registration, rendering or save callbacks manually.
|
|
|
15
15
|
| --- | --- |
|
|
16
16
|
| `DANCE_MOVES_VERSION` | `2.8.0` |
|
|
17
17
|
| `KS_EPK_ORIENTATION_VERSION` | Alias of `DANCE_MOVES_VERSION`. |
|
|
18
|
-
| `KS_EPK_MOTION_CAPTURE_TOKEN` |
|
|
18
|
+
| `KS_EPK_MOTION_CAPTURE_TOKEN` | Removed in 3.1.23. No fixed/published token authorizes capture writes. See the current capture security section. |
|
|
19
19
|
| `DANCE_MOVES_META_BPM` | `_dance_moves_bpm` |
|
|
20
20
|
| `DANCE_MOVES_META_LYRIC_TIMING` | `_dance_moves_lyric_timing_id` |
|
|
21
21
|
| `DANCE_MOVES_META_CUE_TIMING` | `_dance_moves_cue_timing_id` |
|
|
@@ -172,7 +172,7 @@ The full validator runs when the Page editor saves the selected attachment.
|
|
|
172
172
|
```text
|
|
173
173
|
POST <WordPress REST root>/ks-epk-motion/v1/capture
|
|
174
174
|
Content-Type: application/json
|
|
175
|
-
X-
|
|
175
|
+
X-WP-Nonce: <fresh wp_rest nonce for the signed-in administrator session>
|
|
176
176
|
```
|
|
177
177
|
|
|
178
178
|
Implemented by `ks_epk_motion_register_rest_route()` using
|
|
@@ -180,23 +180,48 @@ Implemented by `ks_epk_motion_register_rest_route()` using
|
|
|
180
180
|
`ks_epk_motion_capture_permission(WP_REST_Request $request)` and handler
|
|
181
181
|
`ks_epk_motion_store_capture(WP_REST_Request $request)`.
|
|
182
182
|
|
|
183
|
-
|
|
183
|
+
In 3.1.23, permission processing is:
|
|
184
|
+
|
|
185
|
+
1. WordPress authenticates the request before the permission callback. Cookie
|
|
186
|
+
clients send same-origin credentials and a fresh `wp_rest` nonce in
|
|
187
|
+
`X-WP-Nonce`; WordPress validates that nonce. Missing/expired cookie nonces
|
|
188
|
+
cannot establish administrator authorization. Standard WordPress Application
|
|
189
|
+
Password authentication over HTTPS may also establish the current user;
|
|
190
|
+
this plugin does not create or store those credentials.
|
|
191
|
+
2. Require `current_user_can('manage_options')`. Anonymous requests return 401;
|
|
192
|
+
authenticated callers lacking that capability return 403. The former
|
|
193
|
+
`X-KS-Motion-Token` header is ignored and its public constant is removed.
|
|
194
|
+
3. When `get_http_origin()` supplies an origin, require it to equal `home_url()`
|
|
195
|
+
after trailing-slash removal. A missing Origin is allowed only after genuine
|
|
196
|
+
WordPress authentication/authorization, for example an authorized API client.
|
|
197
|
+
4. Rate-limit by authenticated user ID, using `ks_motion_user_<id>`. Eight
|
|
198
|
+
accepted permission checks are allowed before 429. Each allowed check writes
|
|
199
|
+
a ten-minute expiry; a later-invalid payload still consumes a check. Denied
|
|
200
|
+
callers and other administrators cannot exhaust an administrator's quota.
|
|
201
|
+
|
|
202
|
+
The development lab's static HTML carries no real nonce. Populate its
|
|
203
|
+
`ksMotionCaptureConfig.restNonce` from the current administrator session, not a
|
|
204
|
+
committed value. A registered harness on an authenticated WordPress admin screen
|
|
205
|
+
can use the normal script configuration route:
|
|
184
206
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
```php
|
|
208
|
+
if (current_user_can('manage_options')) {
|
|
209
|
+
// Run after registering/enqueuing your own capture harness script.
|
|
210
|
+
wp_localize_script('your-capture-harness', 'ksMotionCaptureConfig', array(
|
|
211
|
+
'endpoint' => esc_url_raw(rest_url('ks-epk-motion/v1/capture')),
|
|
212
|
+
'restNonce' => wp_create_nonce('wp_rest'),
|
|
213
|
+
));
|
|
214
|
+
}
|
|
215
|
+
```
|
|
192
216
|
|
|
193
|
-
|
|
194
|
-
endpoint
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
217
|
+
The capture client sends `credentials: 'same-origin'` and rejects a different
|
|
218
|
+
endpoint origin before transmitting a nonce or recording. A missing nonce leaves
|
|
219
|
+
local recording/download available and displays an accurate upload hold. After
|
|
220
|
+
a session/nonce expires, reload the authorized configuration before retrying.
|
|
221
|
+
Sensor consent and the explicit upload button remain separate requirements.
|
|
222
|
+
See WordPress's [REST authentication](https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/)
|
|
223
|
+
and [permission callback](https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/#permissions-callback)
|
|
224
|
+
documentation. No custom authentication mechanism is added.
|
|
200
225
|
|
|
201
226
|
### Request shape
|
|
202
227
|
|
|
@@ -275,9 +300,9 @@ Success returns a normal REST response (no explicit 201 status is set):
|
|
|
275
300
|
|
|
276
301
|
| HTTP status | Error code | Meaning |
|
|
277
302
|
| --- | --- | --- |
|
|
278
|
-
| 403 | `ks_motion_forbidden` |
|
|
303
|
+
| 401 / 403 | `ks_motion_forbidden` | WordPress caller is anonymous / lacks `manage_options`. |
|
|
279
304
|
| 403 | `ks_motion_origin` | Supplied origin does not match the site. |
|
|
280
|
-
| 429 | `ks_motion_rate` |
|
|
305
|
+
| 429 | `ks_motion_rate` | This administrator's permission-check quota exhausted. |
|
|
281
306
|
| 400 | `ks_motion_schema` | Missing/wrong schema or nonarray JSON payload. |
|
|
282
307
|
| 400 | `ks_motion_samples` | Missing/nonarray samples or input count outside 1–500. |
|
|
283
308
|
| 400 | `ks_motion_invalid_samples` | At least one required sample field is invalid. |
|
|
@@ -292,9 +317,12 @@ A successful record is a `private` post of type `ks_motion_capture`, titled
|
|
|
292
317
|
`Phone motion capture <site-local date/time>`, with the cleaned JSON in
|
|
293
318
|
`post_content`. Extra metadata: `_ks_motion_passed` (`'1'`/`'0'`),
|
|
294
319
|
`_ks_motion_sample_count`, and `_ks_motion_sha256` (hash of stored encoded JSON).
|
|
295
|
-
The post
|
|
296
|
-
`
|
|
297
|
-
|
|
320
|
+
The post author is the authenticated administrator ID. The post type has a
|
|
321
|
+
Tools-menu UI, title/editor support, `public: false`, and `show_in_rest: false`.
|
|
322
|
+
In 3.1.23 its read, create, edit and delete capabilities all require
|
|
323
|
+
`manage_options`, with generic post meta-capability mapping disabled. Ordinary
|
|
324
|
+
editors/authors cannot acquire access to private sensor captures through their
|
|
325
|
+
normal post-editing capabilities. Retention remains an explicit operator duty.
|
|
298
326
|
|
|
299
327
|
There is **no plugin GET/list/delete capture REST route, retention job, automatic
|
|
300
328
|
capture upload, or cryptographic proof of native sensor provenance**. Private
|
|
@@ -323,6 +351,24 @@ available. Do not assume a root exists merely because the shared script loaded.
|
|
|
323
351
|
|
|
324
352
|
## Registered hooks and callback reference
|
|
325
353
|
|
|
354
|
+
### Project prefixes and compatibility
|
|
355
|
+
|
|
356
|
+
Production PHP declarations use `dance_moves_` / `ks_epk_` functions and
|
|
357
|
+
`DANCE_MOVES_` / `KS_EPK_` constants. Plugin-owned metadata, transients, post
|
|
358
|
+
types, REST namespaces and asset handles use the existing `dance_moves`,
|
|
359
|
+
`dance-moves`, `ks_motion`, `ks-epk-motion` or `ks-epk-device-orientation`
|
|
360
|
+
prefixes. Localized JavaScript configuration uses the named `danceMoves*` and
|
|
361
|
+
`ksEpkOrientationConfig` objects. WordPress core hook names in the table below
|
|
362
|
+
are consumed hooks; they must retain their core names.
|
|
363
|
+
|
|
364
|
+
These names remain for installed-site compatibility. In 3.1.23 the obsolete
|
|
365
|
+
public token constant is removed and the authenticated quota uses the prefixed
|
|
366
|
+
`ks_motion_user_<id>` transient. The declaration-prefix regression and capture
|
|
367
|
+
authorization/client tests run in the existing legacy test gate. Hosted CI also
|
|
368
|
+
exercises real WordPress core nonce validation, roles, REST dispatch, database
|
|
369
|
+
storage and capability mapping on a disposable site. It does not use a live
|
|
370
|
+
installation or claim physical phone acceptance.
|
|
371
|
+
|
|
326
372
|
These are WordPress hooks **consumed** by the plugin, not plugin-defined extension
|
|
327
373
|
hooks. Default priority is 10 unless shown. No `apply_filters('dance_moves_...')`
|
|
328
374
|
or `do_action('dance_moves_...')` extension contract is exposed in this baseline.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Audio-derived recording playback
|
|
2
|
+
|
|
3
|
+
DanceMoves 3.2.0 adds `runtime.recordings` for the bounded `dancerudiments.recording`
|
|
4
|
+
v1 JSON format exported by StemLab and DanceRudiments 0.3.0. Named native patterns
|
|
5
|
+
continue to loop at their own periods. Recordings retain their captured origin,
|
|
6
|
+
64-pip resolution, named dimensions and exact extent; they never wrap or interpolate.
|
|
7
|
+
|
|
8
|
+
```js
|
|
9
|
+
const recording = await runtime.recordings.load('/approved-motion.json');
|
|
10
|
+
const motion = runtime.recordings.animate({
|
|
11
|
+
id: 'subject:recording', root, target, audio,
|
|
12
|
+
recording,
|
|
13
|
+
render({values, reason}) {
|
|
14
|
+
// Map bounded native samples to the existing subject's appearance.
|
|
15
|
+
// A CSSOM rule avoids high-frequency inline-style mutation observers.
|
|
16
|
+
rule.style.setProperty('--subject-angle', `${values[0] * 6}deg`);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
await motion.ready;
|
|
20
|
+
motion.setEnabled(false); // neutral values, preserving the captured clock
|
|
21
|
+
motion.setEnabled(true);
|
|
22
|
+
motion.destroy();
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The controller composes the existing native DanceMoves audio scheduler and its
|
|
26
|
+
shared-player mapping. Pause holds the source pose; seeking reconstructs it.
|
|
27
|
+
Reduced motion, forced colours and explicit disable output zeroes. Hidden and
|
|
28
|
+
offscreen subjects suspend through the existing lifecycle. Positions outside the
|
|
29
|
+
recording emit zeroes with `reason: 'outside-recording'`; seeking back into the
|
|
30
|
+
capture resumes its exact native sample. Runtime disposal destroys all recording
|
|
31
|
+
controllers, including pending native loads. Use `pause()`, `resume()`, `refresh()`,
|
|
32
|
+
`snapshot()`, `recordings.get(id)` and `recordings.snapshot()` for ownership and QA.
|
|
33
|
+
|
|
34
|
+
The recording BPM must match the authoritative runtime/page BPM. A controller
|
|
35
|
+
cannot override tempo, rate, phase or clock. BPM provenance and phase provenance
|
|
36
|
+
remain separate. The page's WordPress EPK Timing metadata remains the only source
|
|
37
|
+
for lyric/cue attachments; a movement recording never replaces those fields.
|
|
38
|
+
Use the exact track/master, same-clock stem provenance and original capture origin.
|
|
39
|
+
StemLab owns separation, filtering and smoothing; this player performs no DSP.
|
|
40
|
+
All smoothing variants should use a fixed reference scale for a fair comparison.
|
|
41
|
+
|
|
42
|
+
The sampler is the official native C++/WebAssembly accessor from DanceRudiments
|
|
43
|
+
0.3.0. There is no JavaScript movement fallback. Its embedded binary SHA-256 is
|
|
44
|
+
`d4cd976156860aa7a5c9665b27d2fda3cf6a0fa0da3dc0b9df365e425f1c6e29`, built from
|
|
45
|
+
upstream `include/dancerudiments/recording_view.hpp` SHA-256
|
|
46
|
+
`19dd73a150a82c4d9074fe4b9ba4c2f09d41e206028a6a6dc922d94e00dc4b8d` and
|
|
47
|
+
`tools/recording_wasm.cpp` SHA-256
|
|
48
|
+
`f4713cc7c773fa065715383fc68dccd91398fff08cd89167c5f24e64c0cecea9`.
|
|
49
|
+
See the [upstream recording contract](https://github.com/kieransimkin/DanceRudiments/blob/v0.3.0/docs/recordings.md).
|
|
50
|
+
The existing bundled named catalogue and its separate version are unchanged.
|
|
51
|
+
|
|
52
|
+
Inputs are limited to 64 MiB JSON, 8,388,608 finite values in [-1,1], 1..64 unique
|
|
53
|
+
named dimensions and signed 32-bit integer pip bounds. Loading fails closed for
|
|
54
|
+
bad UTF-8, schema, samples, HTTP responses, mismatched BPM or unavailable WASM.
|
|
55
|
+
Treat `ready` rejection as an unavailable motion state and retain static content.
|
|
56
|
+
These source/build changes do not deploy a WordPress plugin or page.
|
package/lib/build-manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "dancemoves-library-build/v1",
|
|
3
3
|
"name": "@kieransimkin/dancemoves",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.2.0",
|
|
5
5
|
"homepage": "https://kieransimkin.co.uk/my-songs/",
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
@@ -31,23 +31,23 @@
|
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
"path": "dancemoves.min.js",
|
|
34
|
-
"bytes":
|
|
35
|
-
"sha256": "
|
|
34
|
+
"bytes": 218383,
|
|
35
|
+
"sha256": "9a9afad98cbf15d3c8394a54809596d1ffe784f5ac7ca13484186ace3eb93661"
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
"path": "index.cjs",
|
|
39
|
-
"bytes":
|
|
40
|
-
"sha256": "
|
|
39
|
+
"bytes": 370576,
|
|
40
|
+
"sha256": "ca7ed8da52270ee4a17f94672121f4182fa5cc8c5964c8d095a682978d1b4981"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"path": "index.d.ts",
|
|
44
|
-
"bytes":
|
|
45
|
-
"sha256": "
|
|
44
|
+
"bytes": 14929,
|
|
45
|
+
"sha256": "477a8d665f245dbcff92cdc17372f39b54dbe3f9392695a00773f43b92288914"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"path": "index.mjs",
|
|
49
|
-
"bytes":
|
|
50
|
-
"sha256": "
|
|
49
|
+
"bytes": 369431,
|
|
50
|
+
"sha256": "6edacb0ded30311fc26bb80e86c772ba362c1b60c54a68b5ebaa2d3eb484ac16"
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"path": "react.cjs",
|
|
@@ -106,8 +106,8 @@
|
|
|
106
106
|
},
|
|
107
107
|
{
|
|
108
108
|
"path": "wordpress.js",
|
|
109
|
-
"bytes":
|
|
110
|
-
"sha256": "
|
|
109
|
+
"bytes": 217191,
|
|
110
|
+
"sha256": "1b02054111edf66b3a5766c7da74291fe597d2ed3ac7a89f0f282cfb99c415df"
|
|
111
111
|
}
|
|
112
112
|
]
|
|
113
113
|
}
|