Adom Wiki
Public Made by Adomby adom
How the Adom Wiki (wiki.adom.inc) works and how to drive it with the adom-wiki CLI: the two storage layers (git page repo vs package registry), hosting source by pushing files (not a tarball), making packages, cutting per-platform releases, and the three-tier skill layout (user skills ship, dev-skills/ and publish-skills/ stay source-only). adom-wiki is the current tool; adompkg is deprecated. Read this first before publishing or installing.
Private-page media in widget frames: mint a short-lived signed read URL (third-party cookie blocking breaks ::adom-video on private pages)
Symptom. ::adom-video (adom/widgets) does not play a video stored on a PRIVATE page in real Chrome (third-party cookies blocked) or Safari. In pup's browser it plays. Repro on a private scratch page I own: john/adom-video-test, embeds 2, 3 and 6. The private-manifest form ::adom-video{src="/OWNER/SLUG/render/x.video.json"} behaves the same: the manifest inlines fine (chapters and captions show), but duration stays null.
Cause. Widget frames are served with a CSP sandbox and no allow-same-origin, so the frame is opaque-origin. Its media request to wiki.adom.inc is cross-site from the browser's point of view. The session cookie is SameSite=None; Secure, which is right, but any browser that blocks third-party cookies drops it (Safari always, Chrome with that setting). The request arrives anonymous, and the private file answers 404. There is no URL-borne credential the widget could use instead: ?token= / ?access_token= are ignored, and presigned URLs exist only for uploads.
Ask: a short-lived signed read URL, minted by the server when it renders the widget frame for a viewer who has read access.
- Rewrite every same-page file reference the frame will load to
/api/pages/OWNER/SLUG/files/PATH?sig=…&exp=…. That covers the tag'svideo,poster,captionsandchaptersattributes, and the same fields inside an inlinedsrcmanifest. Use an HMAC over owner, slug, path and expiry (viewer id optional). Scope each signature to that one path. A TTL of a few hours covers a long video; reloading the frame mints fresh ones. - Honor
Rangeon the signed URL (206,Content-Range,Accept-Ranges), as the files API already does with a cookie. - Viewers without access get the frame's existing 404 and no URL minted, so nothing leaks. Reject a wrong path or an expired
exp. - No widget change is needed if the URLs are rewritten in place: adom-video loads whatever URL it is given, and it leaves
/api/pages/…/files/…URLs untouched.
Related finding: /render/ caps file size. /OWNER/SLUG/render/PATH answers 413 {"error":"File too large to render"} for files above roughly 4 to 5 MB, with or without Range and with any auth: a 5.68 MB MP4 is refused, a 3.85 MB one is served. The files API serves the same file with 206. adom-video already streams through the files API, but a README <video src=".../render/..."> of a normal-size demo video gets nothing. Raise the cap for media, or make /render/ stream ranged like the files API (see also #225).
Acceptance (please add as a regression test)
- A 14 MB private MP4 on a private page, both tag forms, plays and seeks for a logged-in viewer with access in Chrome with third-party cookies blocked, in Edge and in Safari.
- Poster, captions and chapters show.
- A logged-out viewer gets nothing.
- A signed URL for a different path, or past
exp, is refused.
Stopgap shipped in the widget (adom/widgets, today). When the stream is refused in the frame, adom-video shows "This video can't play inside the page" with a Play it in a new tab button. That opens the file as a first-party page, where it plays with seeking.