@fuzdev/fuz_ui 0.191.3 → 0.192.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.
Files changed (66) hide show
  1. package/dist/ApiModulesList.svelte +3 -3
  2. package/dist/ColorSchemeInput.svelte +6 -6
  3. package/dist/ContextmenuLinkEntry.svelte +1 -1
  4. package/dist/ContextmenuRoot.svelte +10 -10
  5. package/dist/ContextmenuRootForSafariCompatibility.svelte +19 -19
  6. package/dist/ContextmenuSeparator.svelte +3 -3
  7. package/dist/ContextmenuSubmenu.svelte +3 -3
  8. package/dist/CopyToClipboard.svelte +3 -3
  9. package/dist/DeclarationLink.svelte +1 -1
  10. package/dist/Dialog.svelte +16 -16
  11. package/dist/Docs.svelte +9 -9
  12. package/dist/DocsFooter.svelte +2 -2
  13. package/dist/DocsList.svelte +7 -7
  14. package/dist/DocsMenu.svelte +1 -1
  15. package/dist/DocsPageLinks.svelte +4 -4
  16. package/dist/DocsPrimaryNav.svelte +2 -2
  17. package/dist/DocsSecondaryNav.svelte +4 -4
  18. package/dist/DocsTertiaryNav.svelte +6 -6
  19. package/dist/GithubLink.svelte +1 -1
  20. package/dist/Hashlink.svelte +2 -2
  21. package/dist/HueInput.svelte +6 -6
  22. package/dist/LibraryDetail.svelte +8 -8
  23. package/dist/LibrarySummary.svelte +4 -4
  24. package/dist/MdnLink.svelte +1 -1
  25. package/dist/ModuleLink.svelte +1 -1
  26. package/dist/PasteFromClipboard.svelte +1 -1
  27. package/dist/PendingAnimation.svelte +2 -2
  28. package/dist/PendingButton.svelte +2 -2
  29. package/dist/ProjectLinks.svelte +4 -4
  30. package/dist/Teleport.svelte +2 -2
  31. package/dist/ThemeInput.svelte +5 -5
  32. package/dist/TomeContent.svelte +1 -1
  33. package/dist/TomeHeader.svelte +3 -3
  34. package/dist/TomeLink.svelte +1 -1
  35. package/dist/TomeSection.svelte +1 -1
  36. package/dist/TomeSectionHeader.svelte +3 -3
  37. package/dist/api_search.svelte.js +2 -2
  38. package/dist/contextmenu_state.svelte.d.ts.map +1 -1
  39. package/dist/contextmenu_state.svelte.js +10 -8
  40. package/dist/csp.d.ts +81 -90
  41. package/dist/csp.d.ts.map +1 -1
  42. package/dist/csp.js +150 -163
  43. package/dist/csp_of_fuzdev.d.ts +13 -3
  44. package/dist/csp_of_fuzdev.d.ts.map +1 -1
  45. package/dist/csp_of_fuzdev.js +23 -7
  46. package/dist/dimensions.svelte.d.ts.map +1 -1
  47. package/dist/dimensions.svelte.js +2 -2
  48. package/dist/library.svelte.d.ts +1 -1
  49. package/dist/library_generate.js +1 -1
  50. package/dist/style_variable_helpers.svelte.d.ts.map +1 -1
  51. package/dist/style_variable_helpers.svelte.js +1 -1
  52. package/dist/theme_state.svelte.d.ts.map +1 -1
  53. package/dist/theme_state.svelte.js +2 -2
  54. package/dist/tsdoc_helpers.d.ts +9 -0
  55. package/dist/tsdoc_helpers.d.ts.map +1 -1
  56. package/dist/tsdoc_helpers.js +15 -5
  57. package/package.json +6 -6
  58. package/src/lib/api_search.svelte.ts +2 -2
  59. package/src/lib/contextmenu_state.svelte.ts +9 -8
  60. package/src/lib/csp.ts +229 -259
  61. package/src/lib/csp_of_fuzdev.ts +24 -8
  62. package/src/lib/dimensions.svelte.ts +2 -2
  63. package/src/lib/library_generate.ts +1 -1
  64. package/src/lib/style_variable_helpers.svelte.ts +1 -1
  65. package/src/lib/theme_state.svelte.ts +2 -2
  66. package/src/lib/tsdoc_helpers.ts +18 -7
package/dist/csp.d.ts CHANGED
@@ -1,121 +1,112 @@
1
- import type { ArrayElement, Defined } from '@fuzdev/fuz_util/types.js';
1
+ import type { Defined } from '@fuzdev/fuz_util/types.js';
2
+ /**
3
+ * Per-directive map of source arrays — accepted as `extend` layer entries.
4
+ * Excludes directives like `'upgrade-insecure-requests'` (boolean) that can't be appended to.
5
+ */
6
+ export type CspDirectiveSourcesMap = {
7
+ [K in CspDirective as CspDirectives[K] extends ReadonlyArray<any> ? K : never]?: CspDirectives[K];
8
+ };
9
+ /**
10
+ * Options for `create_csp_directives`.
11
+ *
12
+ * The pipeline runs in three stages:
13
+ * 1. `replace_defaults` sets the starting state (defaults to `csp_directive_value_defaults`).
14
+ * 2. `extend` appends sources per directive, layered left to right.
15
+ * 3. `overrides` replaces or removes per-directive values as a final pass.
16
+ */
2
17
  export interface CreateCspDirectivesOptions {
3
18
  /**
4
- * Override or transform specific directives.
5
- * Returning `null` or `undefined` from a transform function will remove the directive.
19
+ * Starting values per directive — *wholesale replaces* the library defaults.
20
+ *
21
+ * - Omitted: uses `csp_directive_value_defaults` (the curated library defaults).
22
+ * - Provided: exactly the directives you list, nothing else inherited.
23
+ * Anything not listed is **absent** from the starting state — including security defaults
24
+ * like `default-src: 'none'`. To tweak a single directive while keeping the rest, use
25
+ * `extend` (to append) or `overrides` (to replace per-key) instead.
26
+ * - `{}`: starts blank with no directives.
27
+ *
28
+ * `null` is not accepted (top-level or per-key) — omit the option to use library defaults,
29
+ * pass `{}` to start blank, or use `overrides` to remove a specific directive.
30
+ *
31
+ * Per-key `undefined` is treated as omitted (no-op).
6
32
  */
7
- directives?: {
8
- [K in CspDirective]?: CspDirectiveValue<K> | null | ((value: CspDirectiveValue<K>) => CspDirectiveValue<K> | null);
9
- };
10
- /**
11
- * Sources to include based on their trust levels.
12
- */
13
- trusted_sources?: Array<CspSourceSpec>;
33
+ replace_defaults?: Partial<typeof csp_directive_value_defaults>;
14
34
  /**
15
- * Override default values for specific directives,
16
- * merging with `value_defaults_base` (or replacing if that directive is null in the base).
35
+ * Sources to append per directive, layered left to right.
36
+ * Each entry is a partial map; values append to the result of `replace_defaults` and prior entries.
37
+ * Values are deduplicated within and across layers.
38
+ *
39
+ * Only array-typed directives can be extended (boolean directives like `upgrade-insecure-requests`
40
+ * are excluded by the type). Throws if any entry attempts to extend a directive whose current
41
+ * value is `['none']` — use `replace_defaults` or `overrides` to opt into default-deny directives.
42
+ *
43
+ * Per-key `undefined` is treated as omitted (no-op) — supports conditional patterns like
44
+ * `{'connect-src': is_prod ? [API_URL] : undefined}`. Per-key `null` throws — `extend` only
45
+ * appends; use `overrides: { 'X': null }` to remove a directive.
17
46
  */
18
- value_defaults?: Partial<typeof csp_directive_value_defaults>;
47
+ extend?: ReadonlyArray<CspDirectiveSourcesMap>;
19
48
  /**
20
- * Base values for directive defaults.
21
- * Set to `null` or `{}` to start with no defaults.
22
- * Defaults to `csp_directive_value_defaults`.
49
+ * Final-pass per-directive overrides. Replaces the directive value or removes it entirely.
50
+ * Pass `null` to remove a directive from the output.
51
+ *
52
+ * Highest precedence — wins over `replace_defaults` and `extend`.
53
+ *
54
+ * Per-key `undefined` is treated as omitted (no-op) — distinct from `null`, which removes.
23
55
  */
24
- value_defaults_base?: Partial<typeof csp_directive_value_defaults> | null;
25
- /**
26
- * Override trust requirements for specific directives,
27
- * merging with `required_trust_defaults_base` (or replacing if that directive is null in the base).
28
- */
29
- required_trust_defaults?: Partial<typeof csp_directive_required_trust_defaults>;
30
- /**
31
- * Base values for directive trust requirements.
32
- * Set to `null` or `{}` to start with no trust requirements.
33
- * Defaults to `csp_directive_required_trust_defaults`.
34
- */
35
- required_trust_defaults_base?: Partial<typeof csp_directive_required_trust_defaults> | null;
56
+ overrides?: {
57
+ [K in CspDirective]?: CspDirectiveValue<K> | null;
58
+ };
36
59
  }
37
60
  /**
38
- * This is designed for compatibility with SvelteKit
39
- * and maps to the `KitConfig` `directives` option.
40
- * The goal is to provide an ergonomic, modern, and safe API
41
- * for Content Security Policy (CSP) creation
42
- * that's simple to write and audit, and isn't error-prone.
61
+ * Builds a CSP directives map for use with SvelteKit's `kit.csp.directives` option.
43
62
  *
44
- * Things like validation and rendering to a string
45
- * are out of scope and left to SvelteKit.
63
+ * Restrictive by default; opt into specific permissions via `extend` (append) or
64
+ * `overrides` (replace). Designed to read as an audit log: every user-added source
65
+ * is named at exactly one site in the source code. Library defaults are inherited
66
+ * unless you opt out via `replace_defaults`.
67
+ *
68
+ * Validation:
69
+ * - Unknown directive keys throw.
70
+ * - Extending a `['none']` directive throws (use `replace_defaults`/`overrides` to opt in).
71
+ * - `null` for `replace_defaults` (top-level or per-key) throws — omit the option for library
72
+ * defaults, pass `{}` to start blank, or use `overrides` to remove a specific directive.
73
+ * - `null` per-key in `extend` throws (use `overrides` for removal).
74
+ * - `undefined` per-key is treated as omitted in all three stages.
75
+ * - Non-object entries in `extend` (`null`, `undefined`, primitives) throw with a friendly error.
76
+ * - Output is validated to ensure `'none'` never appears alongside other tokens,
77
+ * that no directive ends up with an empty array (use `['none']` to forbid all),
78
+ * and that every source array contains only strings.
79
+ *
80
+ * Things like rendering to a string are out of scope and left to SvelteKit.
46
81
  */
47
- export declare function create_csp_directives(options?: CreateCspDirectivesOptions): CspDirectives;
82
+ export declare const create_csp_directives: (options?: CreateCspDirectivesOptions) => CspDirectives;
48
83
  export type CspDirective = keyof CspDirectives;
49
84
  export declare const parse_csp_directive: (directive: unknown) => CspDirective | null;
50
85
  export type CspDirectiveValue<T extends CspDirective> = Defined<CspDirectives[T]>;
51
- export declare const csp_trust_levels: readonly ["low", "medium", "high"];
52
- /**
53
- * Numeric values for CSP trust levels. See `csp_trust_levels`.
54
- * Lower is less trusted.
55
- * Includes `undefined` in the type for safety.
56
- */
57
- export declare const csp_trust_level_value: Record<CspTrustLevel, number | undefined>;
86
+ export declare const COLOR_SCHEME_SCRIPT_HASH = "sha256-QOxqn7EUzb3ydF9SALJoJGWSvywW9R0AfTDSenB83Z8=";
58
87
  /**
59
- * Trust levels for CSP sources.
60
- *
61
- * With the base defaults, trust levels roughly correspond to:
88
+ * The library CSP directive defaults — directives enabled out of the box.
89
+ * Prioritizes safety but loosens around media and styles, relying on defense-in-depth.
90
+ * WASM compile is allowed (`'wasm-unsafe-eval'` on `script-src` and `worker-src`); `eval` is not.
62
91
  *
63
- * - `low` – Passive resources only (no script execution, no styling or UI control).
64
- * Examples: `img-src`, `font-src`.
65
- * - `medium` – Content that may affect layout, styling, or embed external browsing contexts,
66
- * but cannot directly run code in the page's JS execution environment or
67
- * perform other high-risk actions. Examples: `style-src`, `frame-src`, `frame-ancestors`.
68
- * - `high` – Sources that can execute code in the page's context or open powerful network
69
- * channels. Examples: `script-src`, `connect-src`, `child-src`.
70
- * - `null` – No trust. This is used for directives that don't support sources.
92
+ * Directives not listed here (`report-to`, `require-trusted-types-for`, `trusted-types`,
93
+ * `sandbox`) are intentionally absent by default — opt in via `replace_defaults` or `overrides`.
71
94
  *
95
+ * Customizable via `CreateCspDirectivesOptions.replace_defaults`.
72
96
  */
73
- export type CspTrustLevel = ArrayElement<typeof csp_trust_levels>;
74
- /**
75
- * Validates and extracts a CSP trust level from an unknown value.
76
- */
77
- export declare const parse_csp_trust_level: (trust: unknown) => CspTrustLevel | null;
78
- export interface CspSourceSpec {
79
- source: CspSource;
80
- trust?: CspTrustLevel;
81
- directives?: Array<CspDirective>;
82
- }
97
+ export declare const csp_directive_value_defaults: Partial<{
98
+ [K in CspDirective]: CspDirectiveValue<K>;
99
+ }>;
83
100
  export interface CspDirectiveSpec {
84
101
  name: CspDirective;
85
102
  fallback: Array<CspDirective> | null;
86
103
  fallback_of: Array<CspDirective> | null;
87
104
  }
88
- /**
89
- * Determines if a granted trust level is sufficient to satisfy a required trust level.
90
- *
91
- * Trust levels have the following hierarchy:
92
- * - 'high' sources can be used in high, medium, and low trust directives (highest privilege)
93
- * - 'medium' sources can be used in medium and low trust directives
94
- * - 'low' sources can only be used in low trust directives (lowest privilege)
95
- */
96
- export declare const is_csp_trusted: (required_trust: CspTrustLevel | null | undefined, granted_trust: CspTrustLevel | null | undefined) => boolean;
97
- export declare const COLOR_SCHEME_SCRIPT_HASH = "sha256-QOxqn7EUzb3ydF9SALJoJGWSvywW9R0AfTDSenB83Z8=";
98
- /**
99
- * The base CSP directive defaults.
100
- * Prioritizes safety but loosens around media and styles, relying on defense-in-depth.
101
- * Customizable via `CreateCspDirectivesOptions`.
102
- */
103
- export declare const csp_directive_value_defaults: Record<CspDirective, CspDirectiveValue<CspDirective> | null>;
104
- /**
105
- * Sources that meet this trust requirement are included for it by default.
106
- * If null, no trusted sources are added to the directive automatically.
107
- * Directives that don't support sources or default to `['none']` are null.
108
- *
109
- * Feedback is welcome, please see the issues - https://github.com/fuzdev/fuz_ui/issues
110
- */
111
- export declare const csp_directive_required_trust_defaults: Record<CspDirective, CspTrustLevel | null>;
112
105
  /**
113
106
  * Static data descriptors for the CSP directives.
114
107
  * Fuz excludes deprecated directives, so those are intentionally omitted,
115
108
  * but any newer missing directives are bugs.
116
109
  *
117
- * Could be co-located but is currently here to keep that module smaller.
118
- *
119
110
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy}
120
111
  */
121
112
  export declare const csp_directive_specs: Array<CspDirectiveSpec>;
package/dist/csp.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"csp.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/csp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAE,OAAO,EAAC,MAAM,2BAA2B,CAAC;AAIrE,MAAM,WAAW,0BAA0B;IAC1C;;;OAGG;IACH,UAAU,CAAC,EAAE;SACX,CAAC,IAAI,YAAY,CAAC,CAAC,EACjB,iBAAiB,CAAC,CAAC,CAAC,GACpB,IAAI,GAEJ,CAAC,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;KACjE,CAAC;IAEF;;OAEG;IACH,eAAe,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAEvC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC,OAAO,4BAA4B,CAAC,CAAC;IAE9D;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC,OAAO,4BAA4B,CAAC,GAAG,IAAI,CAAC;IAE1E;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC,OAAO,qCAAqC,CAAC,CAAC;IAEhF;;;;OAIG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC,OAAO,qCAAqC,CAAC,GAAG,IAAI,CAAC;CAC5F;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,0BAA+B,GAAG,aAAa,CAiH7F;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC;AAE/C,eAAO,MAAM,mBAAmB,GAAI,WAAW,OAAO,KAAG,YAAY,GAAG,IAGhE,CAAC;AAET,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,YAAY,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAElF,eAAO,MAAM,gBAAgB,oCAAqC,CAAC;AAEnE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAI3E,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAElE;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,OAAO,KAAG,aAAa,GAAG,IACG,CAAC;AAE3E,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAC1B,gBAAgB,aAAa,GAAG,IAAI,GAAG,SAAS,EAChD,eAAe,aAAa,GAAG,IAAI,GAAG,SAAS,KAC7C,OAWF,CAAC;AASF,eAAO,MAAM,wBAAwB,wDAAwD,CAAC;AAE9F;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAChD,YAAY,EACZ,iBAAiB,CAAC,YAAY,CAAC,GAAG,IAAI,CA0BtC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qCAAqC,EAAE,MAAM,CAAC,YAAY,EAAE,aAAa,GAAG,IAAI,CAyB5F,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,gBAAgB,CAwIvD,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,GAAG,CAAC,YAAY,EAAE,gBAAgB,CAE1E,CAAC;AA8BF,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG,eAAe,CAAC;AACjE,MAAM,MAAM,aAAa,GACtB,MAAM,GACN,aAAa,GACb,eAAe,GACf,eAAe,GACf,kBAAkB,GAClB,MAAM,CAAC;AACV,MAAM,MAAM,eAAe,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,IAAI,MAAM,EAAE,CAAC;AACtF,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,eAAe,GAAG,MAAM,GAAG,MAAM,CAAC;AAC/E,MAAM,MAAM,iBAAiB,GAAG,GAAG,MAAM,IAAI,MAAM,EAAE,GAAG,WAAW,CAAC;AACpE,MAAM,MAAM,aAAa,GAAG,GAAG,sBAAsB,GAAG,iBAAiB,GAAG,aAAa,EAAE,CAAC;AAC5F,MAAM,MAAM,sBAAsB,GAAG,GAAG,MAAM,KAAK,GAAG,EAAE,CAAC;AACzD,MAAM,MAAM,aAAa,GAAG,IAAI,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACrD,MAAM,MAAM,eAAe,GACxB,OAAO,GACP,QAAQ,GACR,OAAO,GACP,cAAc,GACd,OAAO,GACP,aAAa,CAAC;AACjB,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,eAAe,GAAG,eAAe,GAAG,aAAa,CAAC;AAC1F,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC7B,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,eAAe,CAAC,CAAC;IACnD,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,eAAe,CAAC,CAAC;IAClD,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,eAAe,CAAC,CAAC;IACjD,gBAAgB,CAAC,EAAE,UAAU,CAAC;IAC9B,gBAAgB,CAAC,EAAE,UAAU,CAAC;IAC9B,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,UAAU,CAAC;IAC5B,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,iBAAiB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,eAAe,CAAC,CAAC;IACnD,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,eAAe,CAAC,CAAC;IAChD,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,2BAA2B,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9C,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,kBAAkB,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC;IACpE,OAAO,CAAC,EAAE,KAAK,CACZ,yCAAyC,GACzC,aAAa,GACb,cAAc,GACd,wBAAwB,GACxB,oBAAoB,GACpB,cAAc,GACd,gCAAgC,GAChC,oBAAoB,GACpB,mBAAmB,GACnB,eAAe,GACf,yCAAyC,GACzC,sBAAsB,GACtB,yCAAyC,CAC3C,CAAC;CACF"}
1
+ {"version":3,"file":"csp.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/csp.ts"],"names":[],"mappings":"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"}
package/dist/csp.js CHANGED
@@ -1,155 +1,180 @@
1
1
  /**
2
- * This is designed for compatibility with SvelteKit
3
- * and maps to the `KitConfig` `directives` option.
4
- * The goal is to provide an ergonomic, modern, and safe API
5
- * for Content Security Policy (CSP) creation
6
- * that's simple to write and audit, and isn't error-prone.
2
+ * Builds a CSP directives map for use with SvelteKit's `kit.csp.directives` option.
7
3
  *
8
- * Things like validation and rendering to a string
9
- * are out of scope and left to SvelteKit.
4
+ * Restrictive by default; opt into specific permissions via `extend` (append) or
5
+ * `overrides` (replace). Designed to read as an audit log: every user-added source
6
+ * is named at exactly one site in the source code. Library defaults are inherited
7
+ * unless you opt out via `replace_defaults`.
8
+ *
9
+ * Validation:
10
+ * - Unknown directive keys throw.
11
+ * - Extending a `['none']` directive throws (use `replace_defaults`/`overrides` to opt in).
12
+ * - `null` for `replace_defaults` (top-level or per-key) throws — omit the option for library
13
+ * defaults, pass `{}` to start blank, or use `overrides` to remove a specific directive.
14
+ * - `null` per-key in `extend` throws (use `overrides` for removal).
15
+ * - `undefined` per-key is treated as omitted in all three stages.
16
+ * - Non-object entries in `extend` (`null`, `undefined`, primitives) throw with a friendly error.
17
+ * - Output is validated to ensure `'none'` never appears alongside other tokens,
18
+ * that no directive ends up with an empty array (use `['none']` to forbid all),
19
+ * and that every source array contains only strings.
20
+ *
21
+ * Things like rendering to a string are out of scope and left to SvelteKit.
10
22
  */
11
- export function create_csp_directives(options = {}) {
12
- const { directives: directives_option, trusted_sources, value_defaults_base = csp_directive_value_defaults, value_defaults: value_defaults_option, required_trust_defaults_base = csp_directive_required_trust_defaults, required_trust_defaults: required_trust_defaults_option, } = options;
23
+ export const create_csp_directives = (options = {}) => {
24
+ const { replace_defaults = csp_directive_value_defaults, extend, overrides } = options;
25
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
26
+ if (replace_defaults === null) {
27
+ throw new Error(`Invalid value 'null' for options.replace_defaults. ` +
28
+ `Omit the option to use library defaults, or pass {} to start with no directives.`);
29
+ }
13
30
  const directives = {};
14
- // Shallowly merge any provided defaults with the base defaults
15
- const value_defaults = { ...value_defaults_base, ...value_defaults_option };
16
- // Merge required trust defaults with the base
17
- const required_trust_defaults = {
18
- ...required_trust_defaults_base,
19
- ...required_trust_defaults_option,
31
+ // `Object.entries` widens to `[string, unknown]` and TS can't re-narrow per-key, so
32
+ // writes via the validated `directive` need a single trusted-bridge cast — kept inside
33
+ // this helper so the call sites stay free of type assertions. Clones arrays so callers
34
+ // don't have to worry about user-supplied arrays leaking into the output.
35
+ const assign = (directive, value) => {
36
+ directives[directive] = Array.isArray(value)
37
+ ? [...value]
38
+ : value;
20
39
  };
21
- // Apply defaults from directive specs
22
- for (const spec of csp_directive_specs) {
23
- const default_value = value_defaults[spec.name];
24
- if (default_value == null)
25
- continue; // omit null and undefined
26
- directives[spec.name] = Array.isArray(default_value)
27
- ? [...default_value]
28
- : default_value;
29
- }
30
- // Get trust requirements (with overrides applied)
31
- const trust_requirements = new Map();
32
- for (const spec of csp_directive_specs) {
33
- const required_trust = required_trust_defaults[spec.name];
34
- if (required_trust == null)
35
- continue; // omit null and undefined
36
- trust_requirements.set(spec.name, required_trust);
37
- }
38
- // Validate trusted_sources directives
39
- if (trusted_sources?.length) {
40
- for (const spec of trusted_sources) {
41
- if (spec.directives) {
42
- for (const directive of spec.directives) {
43
- if (parse_csp_directive(directive) === null) {
44
- throw new Error(`Invalid directive in trusted_sources: ${directive}`);
45
- }
40
+ // Stage 1: starting state from `replace_defaults`.
41
+ // `{}` starts blank — every directive must come from `extend`/`overrides`.
42
+ for_each_directive(replace_defaults, 'replace_defaults', (directive, value) => {
43
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
44
+ if (value === null) {
45
+ throw new Error(`Invalid value 'null' for directive '${directive}' in options.replace_defaults. ` +
46
+ `Omit the key instead, or use \`overrides: { '${directive}': null }\` to remove.`);
47
+ }
48
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
49
+ if (value === undefined)
50
+ return;
51
+ assign(directive, value);
52
+ });
53
+ // Stage 2: append sources per layer in `extend`.
54
+ if (extend?.length) {
55
+ for (const layer of extend) {
56
+ for_each_directive(layer, 'extend', (directive, value) => {
57
+ // `undefined` is treated as omitted, matching `replace_defaults`/`overrides`.
58
+ // Lets callers write `{'connect-src': cond ? [API] : undefined}` naturally.
59
+ if (value === undefined)
60
+ return;
61
+ // `null` is meaningful enough to deserve its own error — users reaching for null
62
+ // in extend almost always want removal, which lives on `overrides`.
63
+ if (value === null) {
64
+ throw new Error(`Cannot extend directive '${directive}' with null. ` +
65
+ `extend can only append sources — to remove a directive from the output, ` +
66
+ `use \`overrides: { '${directive}': null }\`.`);
46
67
  }
47
- }
68
+ if (!Array.isArray(value)) {
69
+ throw new Error(`Cannot extend directive '${directive}': value must be an array of sources, got ${typeof value}.`);
70
+ }
71
+ if (!value.length)
72
+ return;
73
+ const current = directives[directive];
74
+ if (is_none(current)) {
75
+ throw new Error(`Cannot extend directive '${directive}' while its current value is ['none']. ` +
76
+ `The pipeline runs replace_defaults → extend → overrides, so an \`overrides\` ` +
77
+ `entry for '${directive}' cannot rescue this — extend sees the ['none'] starting ` +
78
+ `value first. Opt in via \`replace_defaults: { '${directive}': [...] }\` or move ` +
79
+ `the sources into \`overrides: { '${directive}': [...] }\`.`);
80
+ }
81
+ if (current === undefined) {
82
+ assign(directive, [...new Set(value)]);
83
+ }
84
+ else if (Array.isArray(current)) {
85
+ assign(directive, [...new Set([...current, ...value])]);
86
+ }
87
+ else {
88
+ throw new Error(`Cannot extend directive '${directive}': it has a non-array value.`);
89
+ }
90
+ });
48
91
  }
49
92
  }
50
- // Apply trusted sources to directives
51
- if (trusted_sources?.length) {
52
- for (const [key, value] of Object.entries(directives)) {
53
- const directive = parse_csp_directive(key);
54
- if (directive === null) {
55
- throw new Error(`Invalid directive in options.directives: ${key}`);
56
- }
57
- // Skip if directive is ['none'] or not an array
58
- if (is_none_directive(value) || !Array.isArray(value)) {
59
- continue;
93
+ // Stage 3: final-pass `overrides` — replace value or remove key.
94
+ if (overrides) {
95
+ for_each_directive(overrides, 'overrides', (directive, value) => {
96
+ if (value === null) {
97
+ delete directives[directive]; // eslint-disable-line @typescript-eslint/no-dynamic-delete
98
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
60
99
  }
61
- // Get required trust for this directive
62
- const required_trust = trust_requirements.get(directive);
63
- if (required_trust == null)
64
- continue;
65
- // Add matching sources - separate the filtering into trust-based and directive-based inclusion
66
- const sources_to_add = trusted_sources
67
- .filter((spec) => {
68
- // Check for explicit inclusion in directives list
69
- const explicitly_included = spec.directives?.includes(directive) ?? false;
70
- // Check for trust level based inclusion
71
- const has_trust_level = spec.trust !== undefined;
72
- const include_by_trust = has_trust_level && is_csp_trusted(required_trust, spec.trust);
73
- // Include the source if either condition is met
74
- return explicitly_included || include_by_trust;
75
- })
76
- .map((spec) => spec.source);
77
- if (sources_to_add.length > 0) {
78
- directives[directive] = [...value, ...sources_to_add];
100
+ else if (value !== undefined) {
101
+ assign(directive, value);
79
102
  }
80
- }
103
+ });
81
104
  }
82
- // Apply directive overrides/transformations
83
- if (directives_option) {
84
- for (const [key, value_or_fn] of Object.entries(directives_option)) {
85
- const directive = parse_csp_directive(key);
86
- if (directive === null) {
87
- throw new Error(`Invalid directive in options.directives: ${key}`);
88
- }
89
- const current = directives[directive];
90
- const result = typeof value_or_fn === 'function' ? value_or_fn(current) : value_or_fn;
91
- // Handle `undefined` too just in case
92
- if (result == null) {
93
- delete directives[directive]; // eslint-disable-line @typescript-eslint/no-dynamic-delete
94
- }
95
- else {
96
- directives[directive] = structuredClone(result);
105
+ // Stage 4: output validation — empty arrays and mixed `'none'` are invalid CSP.
106
+ for (const [key, value] of Object.entries(directives)) {
107
+ if (typeof value === 'boolean')
108
+ continue;
109
+ if (!Array.isArray(value)) {
110
+ throw new Error(`Directive '${key}' has an invalid value: expected an array of sources or a boolean, ` +
111
+ `got ${value === null ? 'null' : typeof value}.`);
112
+ }
113
+ if (value.length === 0) {
114
+ throw new Error(`Directive '${key}' has an empty array. ` +
115
+ `Use ['none'] to forbid all sources, or omit the directive entirely.`);
116
+ }
117
+ // Element-level type check — the `CspSource` template-string type gates this at the
118
+ // type layer, but `as any` callers can slip non-strings through. A non-string source
119
+ // would render as `undefined` / `[object Object]` in the emitted CSP header.
120
+ for (let i = 0; i < value.length; i++) {
121
+ const v = value[i];
122
+ if (typeof v !== 'string') {
123
+ throw new Error(`Directive '${key}' has a non-string source at index ${i}: got ${v === null ? 'null' : typeof v}.`);
97
124
  }
98
125
  }
126
+ if (value.length > 1 && value.includes('none')) {
127
+ throw new Error(`Directive '${key}' has 'none' alongside other tokens (${value.join(', ')}). ` +
128
+ `'none' must appear alone in CSP.`);
129
+ }
99
130
  }
100
131
  return directives;
101
- }
132
+ };
102
133
  export const parse_csp_directive = (directive) => typeof directive === 'string' && csp_directive_spec_by_name.has(directive)
103
134
  ? directive
104
135
  : null;
105
- export const csp_trust_levels = ['low', 'medium', 'high'];
106
- /**
107
- * Numeric values for CSP trust levels. See `csp_trust_levels`.
108
- * Lower is less trusted.
109
- * Includes `undefined` in the type for safety.
110
- */
111
- export const csp_trust_level_value = {
112
- low: 0,
113
- medium: 1,
114
- high: 2,
115
- };
116
- /**
117
- * Validates and extracts a CSP trust level from an unknown value.
118
- */
119
- export const parse_csp_trust_level = (trust) => csp_trust_levels.includes(trust) ? trust : null;
136
+ const is_none = (value) => Array.isArray(value) && value.length === 1 && value[0] === 'none';
120
137
  /**
121
- * Determines if a granted trust level is sufficient to satisfy a required trust level.
138
+ * Iterate over a per-directive options map, validating that every key is a known directive.
139
+ * Throws if any key fails to parse as a `CspDirective`, mentioning `source_label` so the
140
+ * error pinpoints which option (`replace_defaults`, `extend`, or `overrides`) was bad.
122
141
  *
123
- * Trust levels have the following hierarchy:
124
- * - 'high' sources can be used in high, medium, and low trust directives (highest privilege)
125
- * - 'medium' sources can be used in medium and low trust directives
126
- * - 'low' sources can only be used in low trust directives (lowest privilege)
142
+ * Also guards against non-object `source` values (e.g. `extend: [undefined]`, `extend: ['oops']`)
143
+ * so callers get a friendly library error instead of a cryptic native `TypeError` from
144
+ * `Object.entries`.
127
145
  */
128
- export const is_csp_trusted = (required_trust, granted_trust) => {
129
- const required_value = required_trust && csp_trust_level_value[required_trust];
130
- const granted_value = granted_trust && csp_trust_level_value[granted_trust];
131
- if (required_value == null || granted_value == null) {
132
- return false;
146
+ const for_each_directive = (source, source_label, fn) => {
147
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
148
+ if (source === null || typeof source !== 'object') {
149
+ const got = source === null ? 'null' : typeof source; // eslint-disable-line @typescript-eslint/no-unnecessary-condition
150
+ throw new Error(`Invalid entry in options.${source_label}: expected an object, got ${got}.`);
151
+ }
152
+ for (const [key, value] of Object.entries(source)) {
153
+ const directive = parse_csp_directive(key);
154
+ if (directive === null) {
155
+ throw new Error(`Invalid directive in options.${source_label}: ${key}`);
156
+ }
157
+ fn(directive, value);
133
158
  }
134
- // A source with higher trust privilege (higher value)
135
- // can be used in a directive with less privilege (lower value).
136
- return granted_value >= required_value;
137
159
  };
138
- /**
139
- * Helper to check if a directive value is `['none']`,
140
- * or more precisely for robustness with malformed values, checks for an array with `'none'`.
141
- */
142
- const is_none_directive = (value) => Array.isArray(value) && value.includes('none');
143
160
  export const COLOR_SCHEME_SCRIPT_HASH = 'sha256-QOxqn7EUzb3ydF9SALJoJGWSvywW9R0AfTDSenB83Z8=';
144
161
  /**
145
- * The base CSP directive defaults.
162
+ * The library CSP directive defaults — directives enabled out of the box.
146
163
  * Prioritizes safety but loosens around media and styles, relying on defense-in-depth.
147
- * Customizable via `CreateCspDirectivesOptions`.
164
+ * WASM compile is allowed (`'wasm-unsafe-eval'` on `script-src` and `worker-src`); `eval` is not.
165
+ *
166
+ * Directives not listed here (`report-to`, `require-trusted-types-for`, `trusted-types`,
167
+ * `sandbox`) are intentionally absent by default — opt in via `replace_defaults` or `overrides`.
168
+ *
169
+ * Customizable via `CreateCspDirectivesOptions.replace_defaults`.
148
170
  */
149
171
  export const csp_directive_value_defaults = {
150
172
  'default-src': ['none'],
151
- 'script-src': ['self', COLOR_SCHEME_SCRIPT_HASH], // Eval is opt-in, scripting is locked down except for self and the color scheme loader script
152
- 'script-src-elem': ['self', COLOR_SCHEME_SCRIPT_HASH], // Block script elements except for self and the color scheme loader
173
+ // `'wasm-unsafe-eval'` permits WASM compile/instantiate only — `eval` and `new Function`
174
+ // remain blocked. Needed for `@fuzdev/fuz_util/hash_blake3` and any other WASM in the page.
175
+ // Pre-2022 browsers ignore the keyword and block WASM; if you need them, override with `'unsafe-eval'`.
176
+ 'script-src': ['self', 'wasm-unsafe-eval', COLOR_SCHEME_SCRIPT_HASH],
177
+ 'script-src-elem': ['self', COLOR_SCHEME_SCRIPT_HASH], // Block script elements except for self and the color scheme loader (WASM compile is gated by script-src, not script-src-elem)
153
178
  'script-src-attr': ['none'], // Block scripts in HTML attributes
154
179
  'style-src': ['self', 'unsafe-inline'], // Main style directive (uses unsafe-inline but network connections are disallowed by other directives)
155
180
  'style-src-elem': ['self', 'unsafe-inline'], // Style elements (standalone stylesheets)
@@ -163,55 +188,17 @@ export const csp_directive_value_defaults = {
163
188
  'frame-src': ['self'], // Frames/iframes
164
189
  'frame-ancestors': ['self'], // Control what can embed this page
165
190
  'form-action': ['self'], // Form submission targets
166
- 'worker-src': ['self', 'blob:'], // Web workers
191
+ // `'wasm-unsafe-eval'` mirrors the script-src allowance so WASM compiled inside a Web Worker also works.
192
+ 'worker-src': ['self', 'blob:', 'wasm-unsafe-eval'], // Web workers
167
193
  'object-src': ['none'], // Block plugins (Flash, Java, etc.)
168
194
  'base-uri': ['none'], // Prevent base tag hijacking
169
195
  'upgrade-insecure-requests': true, // Upgrade http to https
170
- 'report-to': null, // Report violations (e.g. `'/csp-violation-report'`)
171
- 'require-trusted-types-for': null,
172
- 'trusted-types': null,
173
- sandbox: null,
174
- };
175
- /**
176
- * Sources that meet this trust requirement are included for it by default.
177
- * If null, no trusted sources are added to the directive automatically.
178
- * Directives that don't support sources or default to `['none']` are null.
179
- *
180
- * Feedback is welcome, please see the issues - https://github.com/fuzdev/fuz_ui/issues
181
- */
182
- export const csp_directive_required_trust_defaults = {
183
- 'default-src': null,
184
- 'script-src': 'high',
185
- 'script-src-elem': 'high',
186
- 'script-src-attr': null,
187
- 'style-src': 'medium',
188
- 'style-src-elem': 'medium',
189
- 'style-src-attr': 'medium',
190
- 'img-src': 'low',
191
- 'media-src': 'low',
192
- 'font-src': 'low',
193
- 'manifest-src': null,
194
- 'child-src': null,
195
- 'connect-src': 'medium',
196
- 'frame-src': 'medium',
197
- 'frame-ancestors': 'medium',
198
- 'form-action': 'medium',
199
- 'worker-src': 'medium',
200
- 'object-src': null,
201
- 'base-uri': null,
202
- 'upgrade-insecure-requests': null,
203
- 'report-to': null,
204
- 'require-trusted-types-for': null,
205
- 'trusted-types': null,
206
- sandbox: null,
207
196
  };
208
197
  /**
209
198
  * Static data descriptors for the CSP directives.
210
199
  * Fuz excludes deprecated directives, so those are intentionally omitted,
211
200
  * but any newer missing directives are bugs.
212
201
  *
213
- * Could be co-located but is currently here to keep that module smaller.
214
- *
215
202
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy}
216
203
  */
217
204
  export const csp_directive_specs = [
@@ -1,6 +1,16 @@
1
- import type { CspSourceSpec } from './csp.ts';
1
+ import type { CspDirectives } from './csp.ts';
2
2
  /**
3
- * Trusted sources owned by fuz.dev.
3
+ * Per-directive sources that allow full interop between fuzdev/sister sites
4
+ * (`*.fuz.dev`, `*.zzz.software`) — loading assets and APIs from each other,
5
+ * and iframing in both directions.
6
+ *
7
+ * Pass into `create_csp_directives({extend: [csp_directives_of_fuzdev]})`.
8
+ * Intended for sites within the ecosystem; external apps usually want a
9
+ * narrower, hand-written allow-list.
10
+ *
11
+ * Deliberately scoped — `script-src`, `style-src`, `worker-src`, etc. are not
12
+ * granted, even between sister sites. Add at the call site if a specific page
13
+ * needs them.
4
14
  */
5
- export declare const csp_trusted_sources_of_fuzdev: Array<CspSourceSpec>;
15
+ export declare const csp_directives_of_fuzdev: Partial<CspDirectives>;
6
16
  //# sourceMappingURL=csp_of_fuzdev.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"csp_of_fuzdev.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/csp_of_fuzdev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,6BAA6B,EAAE,KAAK,CAAC,aAAa,CAK9D,CAAC"}
1
+ {"version":3,"file":"csp_of_fuzdev.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/csp_of_fuzdev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,EAAE,OAAO,CAAC,aAAa,CAW3D,CAAC"}