@cavuno/board 4.0.0 → 4.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/{_spec-GVe6WAfT.d.mts → _spec-BnoxU-iR.d.mts} +58 -12
  3. package/dist/{_spec-GVe6WAfT.d.ts → _spec-BnoxU-iR.d.ts} +58 -12
  4. package/dist/{blog-BsmKizpd.d.ts → blog-D-PYhejB.d.ts} +1 -1
  5. package/dist/{blog-Cf64mI8A.d.mts → blog-DoAOCg-d.d.mts} +1 -1
  6. package/dist/{board-DUhgiacm.d.ts → board-4vXzYDL3.d.ts} +2 -2
  7. package/dist/{board-GGWJ4coe.d.mts → board-CvBkK7my.d.mts} +2 -2
  8. package/dist/{breadcrumbs-DiccJhk4.d.ts → breadcrumbs-Blf_rsux.d.ts} +2 -2
  9. package/dist/{breadcrumbs-DFKr0HzU.d.mts → breadcrumbs-Cz1sFqtV.d.mts} +2 -2
  10. package/dist/filters.d.mts +2 -2
  11. package/dist/filters.d.ts +2 -2
  12. package/dist/format.d.mts +4 -4
  13. package/dist/format.d.ts +4 -4
  14. package/dist/index.d.mts +74 -16
  15. package/dist/index.d.ts +74 -16
  16. package/dist/index.js +41 -6
  17. package/dist/index.mjs +41 -6
  18. package/dist/{jobs-QrbXOYB9.d.ts → jobs-B8DNWEir.d.ts} +1 -1
  19. package/dist/{jobs-BuLpV8iy.d.mts → jobs-aTp9uC3a.d.mts} +1 -1
  20. package/dist/{search-Cr4noJJZ.d.mts → search-Cs7d8y1k.d.mts} +1 -1
  21. package/dist/{search-DdsniXQv.d.ts → search-Cskh-neW.d.ts} +1 -1
  22. package/dist/seo.d.mts +6 -6
  23. package/dist/seo.d.ts +6 -6
  24. package/dist/server.d.mts +5 -5
  25. package/dist/server.d.ts +5 -5
  26. package/dist/sitemap.d.mts +5 -5
  27. package/dist/sitemap.d.ts +5 -5
  28. package/dist/suggest.d.mts +2 -2
  29. package/dist/suggest.d.ts +2 -2
  30. package/package.json +1 -1
  31. package/skills/cavuno-board-api-client/SKILL.md +42 -0
  32. package/skills/cavuno-board-seo/SKILL.md +12 -0
  33. package/skills/manifest.json +1 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,57 @@
3
3
  This changelog records changes that affect Board API compatibility, exported
4
4
  types, runtime behavior, or supported integration patterns.
5
5
 
6
+ ## 4.2.0 — 2026-08-06
7
+
8
+ - **Board logo + favicon pack on `board.context()`**: public board context now
9
+ includes `icons` next to `logoUrl` — absolute CDN URLs (or `null`) for
10
+ `ico`, `svg`, `appleTouch`, `icon192`, `icon512`, and `iconMaskable512`.
11
+ Derived from the operator logo (Settings → General upload / logo generator).
12
+ Brand identity, not SEO infra — `board.seo()` stays ads/IndexNow/GSV/
13
+ canonical/manifest.name only. Map `icons` into root-layout favicon `<link>`
14
+ tags. Operators set the logo in Cavuno; the API resolves the pack.
15
+ - **Card `summary` on jobs, companies, and talent**: list/card models gain a
16
+ server-derived plain-text `summary: string | null` — HTML stripped, entities
17
+ decoded, cut at a sentence boundary (or word boundary with `…`). The API does
18
+ the data cleaning; consumers decide how much of the string to show.
19
+ - `PublicJobCard.summary` — denormalized at write time on
20
+ `publicJobCardDocs` (backfill migration
21
+ `jobs/migrations:backfillPublicJobCardSummary`). Independent of the
22
+ existing `?fields=+description` opt-in, which keeps working as before.
23
+ - `CompanyPublic.summary` — derived from `description` at serialization for
24
+ list, search, and similar. Detail still ships the full HTML body.
25
+ - `TalentDirectoryEntry.summary` — derived from `bio` at serialization.
26
+ - **Deprecations** (still returned; prefer `summary` for card teasers):
27
+ - `CompanyPublic.description` on list/search/similar
28
+ - `TalentDirectoryEntry.bio`
29
+
30
+ ## 4.1.0 — 2026-08-06
31
+
32
+ - **Salary null-clears on job PATCH** (operator `PATCH /v1/jobs/:id` and
33
+ employer `PATCH /v1/boards/:identifier/me/companies/:slug/jobs/:id`):
34
+ `salaryMin`, `salaryMax`, `salaryCurrency`, and `salaryTimeframe` now
35
+ accept an explicit `null` meaning "clear the stored value" — the same
36
+ tri-state `applicationUrl` and `expiresAt` already document (value sets,
37
+ `null` clears, omitted leaves unchanged). Clearing also drops the derived
38
+ USD figures, so salary filters stop matching a job whose salary was
39
+ withdrawn.
40
+ - **Structured remote fields on `PublicJobCard`**: `remoteWorldwide`
41
+ (`boolean | null`) and `remoteWorkPermitCountryCodes` (`string[]`) beside
42
+ the pre-worded `remoteLocationLabel`, so templates can word remote
43
+ regions from their own catalogs instead of matching the board-language
44
+ `"Worldwide"` label string. Derived from the same permit selection the
45
+ label reads — the boolean and the label always agree.
46
+ - **Docs**: `Plan.name` and `Plan.description` are documented as authoring
47
+ defaults — the localized public string lives in the board template,
48
+ composed from `featureSummary`, `billingInterval`, and `talent`.
49
+ - **Marketing consent**: consent is a property of the board
50
+ user. New `board.me.marketingConsent` namespace — `retrieve()` (the
51
+ consent, or `null` when no decision exists), `grant()`, `withdraw()` —
52
+ plus the `MarketingConsent` type. The API records the decision, never
53
+ the prose: disclosure wording is authored by the board's own frontend.
54
+ - **Outbound webhooks**: webhook subscription endpoints and event types
55
+ join the OpenAPI contract and generated types.
56
+
6
57
  ## 4.0.0 — 2026-08-03
7
58
 
8
59
  - **Lossy seams:** Resolution is fine;
@@ -205,6 +205,8 @@ interface components {
205
205
  /** @description Minimum 8 characters. */
206
206
  password: string;
207
207
  displayName: string;
208
+ /** @description True only when the person ticked a marketing checkbox your UI displayed with its disclosure wording. Omit when no checkbox was shown; false and absent both record nothing. */
209
+ marketingConsent?: boolean;
208
210
  };
209
211
  BoardAuthRequestMagicLinkBody: {
210
212
  /** Format: email */
@@ -436,7 +438,12 @@ interface components {
436
438
  website: string | null;
437
439
  /** @description URL of the company logo, or `null` if no logo is set. */
438
440
  logoUrl: string | null;
439
- /** @description Long-form description of the company, or `null` if not set. */
441
+ /** @description Plain-text card teaser: the operator-authored company summary when set, otherwise a derived teaser from the long-form description (HTML stripped, first sentence / word-boundary cut). `null` when neither yields anything. Prefer this over `description` for list/card renders. */
442
+ summary: string | null;
443
+ /**
444
+ * @deprecated
445
+ * @description Long-form description of the company (HTML), or `null` if not set. **Deprecated on list/search/similar responses** — prefer `summary` for card teasers. Still the full prose for detail pages (`GET …/companies/{slug}`).
446
+ */
440
447
  description: string | null;
441
448
  /** @description Total number of public-facing jobs at this company. Currently mirrors `publishedJobCount`. */
442
449
  jobCount: number;
@@ -866,7 +873,7 @@ interface components {
866
873
  */
867
874
  employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
868
875
  /**
869
- * @description Whether the role is on-site, hybrid, or fully remote.
876
+ * @description Whether the role is on-site, hybrid, or fully remote. **Never valid on its own:** `on_site` and `hybrid` require at least one `officeLocations` entry, and `remote` requires `remotePermits` (use `[{"type":"worldwide","value":"worldwide"}]` for anywhere; `remoteTimezones` then auto-derives on POST). Sending it alone returns `400`.
870
877
  * @enum {string}
871
878
  */
872
879
  remoteOption?: "on_site" | "hybrid" | "remote";
@@ -1111,7 +1118,7 @@ interface components {
1111
1118
  */
1112
1119
  employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
1113
1120
  /**
1114
- * @description Whether the role is on-site, hybrid, or fully remote.
1121
+ * @description Whether the role is on-site, hybrid, or fully remote. **Never valid on its own:** `on_site` and `hybrid` require at least one `officeLocations` entry, and `remote` requires `remotePermits` (use `[{"type":"worldwide","value":"worldwide"}]` for anywhere; `remoteTimezones` then auto-derives on POST). Sending it alone returns `400`.
1115
1122
  * @enum {string}
1116
1123
  */
1117
1124
  remoteOption?: "on_site" | "hybrid" | "remote";
@@ -1140,17 +1147,17 @@ interface components {
1140
1147
  seniority?: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive";
1141
1148
  /** @description Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (normalized to `mailto:` form). Pass `null` to clear the stored value and switch the job to on-board (built-in) applications. Omitted means unchanged. */
1142
1149
  applicationUrl?: string | null;
1143
- /** @description Minimum salary, in `salaryCurrency` units. */
1144
- salaryMin?: number;
1145
- /** @description Maximum salary, in `salaryCurrency` units. */
1146
- salaryMax?: number;
1147
- /** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. */
1148
- salaryCurrency?: string;
1150
+ /** @description Minimum salary, in `salaryCurrency` units. Pass `null` to clear the stored value; omitted means unchanged. */
1151
+ salaryMin?: number | null;
1152
+ /** @description Maximum salary, in `salaryCurrency` units. Pass `null` to clear the stored value; omitted means unchanged. */
1153
+ salaryMax?: number | null;
1154
+ /** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. Pass `null` to clear the stored value; omitted means unchanged. */
1155
+ salaryCurrency?: string | null;
1149
1156
  /**
1150
- * @description Period the `salaryMin` and `salaryMax` figures are quoted against.
1151
- * @enum {string}
1157
+ * @description Period the `salaryMin` and `salaryMax` figures are quoted against. Pass `null` to clear the stored value; omitted means unchanged.
1158
+ * @enum {string|null}
1152
1159
  */
1153
- salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour";
1160
+ salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
1154
1161
  /** @description Up to 100 canonical skill slugs from `GET /v1/taxonomies/skills`. Every slug must exist in this account. */
1155
1162
  skills?: string[];
1156
1163
  /** @description Up to 100 canonical category slugs from `GET /v1/taxonomies/categories`. Every slug must exist in this account. */
@@ -1455,6 +1462,21 @@ interface components {
1455
1462
  /** @description Number of companies on the board in this market. */
1456
1463
  companyCount: number;
1457
1464
  };
1465
+ MarketingConsent: {
1466
+ id: string;
1467
+ /** @enum {string} */
1468
+ object: "marketing_consent";
1469
+ /** @enum {string} */
1470
+ status: "granted" | "withdrawn";
1471
+ source: string;
1472
+ /** @enum {string|null} */
1473
+ reason: "person_request" | "operator_request" | "account_deleted" | null;
1474
+ /** Format: date-time */
1475
+ grantedAt: string | null;
1476
+ /** Format: date-time */
1477
+ withdrawnAt: string | null;
1478
+ revision: number;
1479
+ } | null;
1458
1480
  Message: {
1459
1481
  id: string;
1460
1482
  /** @enum {string} */
@@ -1518,7 +1540,9 @@ interface components {
1518
1540
  /** @enum {string} */
1519
1541
  object: "plan";
1520
1542
  id: string;
1543
+ /** @description The operator's authoring-default plan name, in the board's language. Board templates that localize chrome should treat this as the fallback and word plan names from `featureSummary` structure or their own catalogs. */
1521
1544
  name: string;
1545
+ /** @description Authoring default: the operator's prose description in the board's language. The localized public string lives in the board template — compose it from `featureSummary`, `billingInterval`, and `talent` rather than displaying this verbatim on localized surfaces. */
1522
1546
  description: string | null;
1523
1547
  /** @enum {string} */
1524
1548
  purpose: "job_posting" | "talent_access";
@@ -1646,7 +1670,17 @@ interface components {
1646
1670
  name: string;
1647
1671
  /** @description Board language (ISO code); defaults to "en". */
1648
1672
  language: string;
1673
+ /** @description Absolute URL for the board logo, or null when unset. Operators set this under Settings → General (upload or logo generator); the website builder can manage it too. */
1649
1674
  logoUrl: string | null;
1675
+ /** @description Absolute URLs for the favicon / app-icon pack derived from the board logo (null when a variant is unset). Brand identity next to `logoUrl` — build `<link rel="icon">` tags and the web-manifest icon list from these. Not SEO infra (`board.seo()`). */
1676
+ icons: {
1677
+ ico: string | null;
1678
+ svg: string | null;
1679
+ appleTouch: string | null;
1680
+ icon192: string | null;
1681
+ icon512: string | null;
1682
+ iconMaskable512: string | null;
1683
+ };
1650
1684
  /** @description Active custom-domain hostname, or null. */
1651
1685
  primaryDomain: string | null;
1652
1686
  /** @description Whitelabel toggle (default `true`). Render the "Powered by Cavuno" badge unless `false`. */
@@ -1913,11 +1947,17 @@ interface components {
1913
1947
  remoteOption: "on_site" | "hybrid" | "remote" | null;
1914
1948
  /** @description Display region label for remote jobs (e.g. "United States", "Worldwide"); `null` for non-remote jobs. */
1915
1949
  remoteLocationLabel: string | null;
1950
+ /** @description Structured twin of `remoteLocationLabel`’s "Worldwide" case: `true` when the remote permit selection is unrestricted (explicit worldwide, or no constraint), `false` for a constrained remote job, `null` for non-remote jobs. Word it from your own catalog instead of matching the board-language label string. */
1951
+ remoteWorldwide: boolean | null;
1952
+ /** @description ISO 3166-1 alpha-2 codes the remote permit selection covers (derived expansion, mirroring the job detail field of the same name). Empty for worldwide/unconstrained and non-remote jobs. */
1953
+ remoteWorkPermitCountryCodes: string[];
1916
1954
  salaryMin: number | null;
1917
1955
  salaryMax: number | null;
1918
1956
  salaryCurrency: string | null;
1919
1957
  salaryTimeframe: string | null;
1920
1958
  isFeatured: boolean;
1959
+ /** @description Plain-text card teaser derived from the job description (HTML stripped, first sentence / word-boundary cut). `null` when there is nothing honest to show. Always present — independent of the `?fields=+description` opt-in for the long-form HTML body. Prefer this over requesting `+description` for list/card renders. */
1960
+ summary: string | null;
1921
1961
  locationLabel: string | null;
1922
1962
  /** @description Embedded company summary, or `null` if none is attached. */
1923
1963
  company: {
@@ -2380,6 +2420,12 @@ interface components {
2380
2420
  headline: string | null;
2381
2421
  location: string | null;
2382
2422
  avatarUrl: string | null;
2423
+ /** @description Plain-text card teaser derived from `bio` (HTML stripped, first sentence / word-boundary cut). `null` when there is nothing honest to show. Prefer this over `bio` for directory/card renders; cards still lead with `headline` when present. */
2424
+ summary: string | null;
2425
+ /**
2426
+ * @deprecated
2427
+ * @description Long-form candidate bio. **Deprecated on directory entries** — prefer `summary` for card teasers. Still the full prose on the talent profile detail (`GET …/talent/{handle}`).
2428
+ */
2383
2429
  bio: string | null;
2384
2430
  jobSearchStatus: string | null;
2385
2431
  skills: string[];
@@ -205,6 +205,8 @@ interface components {
205
205
  /** @description Minimum 8 characters. */
206
206
  password: string;
207
207
  displayName: string;
208
+ /** @description True only when the person ticked a marketing checkbox your UI displayed with its disclosure wording. Omit when no checkbox was shown; false and absent both record nothing. */
209
+ marketingConsent?: boolean;
208
210
  };
209
211
  BoardAuthRequestMagicLinkBody: {
210
212
  /** Format: email */
@@ -436,7 +438,12 @@ interface components {
436
438
  website: string | null;
437
439
  /** @description URL of the company logo, or `null` if no logo is set. */
438
440
  logoUrl: string | null;
439
- /** @description Long-form description of the company, or `null` if not set. */
441
+ /** @description Plain-text card teaser: the operator-authored company summary when set, otherwise a derived teaser from the long-form description (HTML stripped, first sentence / word-boundary cut). `null` when neither yields anything. Prefer this over `description` for list/card renders. */
442
+ summary: string | null;
443
+ /**
444
+ * @deprecated
445
+ * @description Long-form description of the company (HTML), or `null` if not set. **Deprecated on list/search/similar responses** — prefer `summary` for card teasers. Still the full prose for detail pages (`GET …/companies/{slug}`).
446
+ */
440
447
  description: string | null;
441
448
  /** @description Total number of public-facing jobs at this company. Currently mirrors `publishedJobCount`. */
442
449
  jobCount: number;
@@ -866,7 +873,7 @@ interface components {
866
873
  */
867
874
  employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
868
875
  /**
869
- * @description Whether the role is on-site, hybrid, or fully remote.
876
+ * @description Whether the role is on-site, hybrid, or fully remote. **Never valid on its own:** `on_site` and `hybrid` require at least one `officeLocations` entry, and `remote` requires `remotePermits` (use `[{"type":"worldwide","value":"worldwide"}]` for anywhere; `remoteTimezones` then auto-derives on POST). Sending it alone returns `400`.
870
877
  * @enum {string}
871
878
  */
872
879
  remoteOption?: "on_site" | "hybrid" | "remote";
@@ -1111,7 +1118,7 @@ interface components {
1111
1118
  */
1112
1119
  employmentType?: "full_time" | "part_time" | "contract" | "internship" | "temporary" | "volunteer" | "other";
1113
1120
  /**
1114
- * @description Whether the role is on-site, hybrid, or fully remote.
1121
+ * @description Whether the role is on-site, hybrid, or fully remote. **Never valid on its own:** `on_site` and `hybrid` require at least one `officeLocations` entry, and `remote` requires `remotePermits` (use `[{"type":"worldwide","value":"worldwide"}]` for anywhere; `remoteTimezones` then auto-derives on POST). Sending it alone returns `400`.
1115
1122
  * @enum {string}
1116
1123
  */
1117
1124
  remoteOption?: "on_site" | "hybrid" | "remote";
@@ -1140,17 +1147,17 @@ interface components {
1140
1147
  seniority?: "entry_level" | "associate" | "mid_level" | "senior" | "lead" | "principal" | "director" | "executive";
1141
1148
  /** @description Where candidates apply. Accepts an HTTPS URL, a `mailto:` URI, or a bare email address (normalized to `mailto:` form). Pass `null` to clear the stored value and switch the job to on-board (built-in) applications. Omitted means unchanged. */
1142
1149
  applicationUrl?: string | null;
1143
- /** @description Minimum salary, in `salaryCurrency` units. */
1144
- salaryMin?: number;
1145
- /** @description Maximum salary, in `salaryCurrency` units. */
1146
- salaryMax?: number;
1147
- /** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. */
1148
- salaryCurrency?: string;
1150
+ /** @description Minimum salary, in `salaryCurrency` units. Pass `null` to clear the stored value; omitted means unchanged. */
1151
+ salaryMin?: number | null;
1152
+ /** @description Maximum salary, in `salaryCurrency` units. Pass `null` to clear the stored value; omitted means unchanged. */
1153
+ salaryMax?: number | null;
1154
+ /** @description Three-letter ISO 4217 currency code for `salaryMin` and `salaryMax`. Pass `null` to clear the stored value; omitted means unchanged. */
1155
+ salaryCurrency?: string | null;
1149
1156
  /**
1150
- * @description Period the `salaryMin` and `salaryMax` figures are quoted against.
1151
- * @enum {string}
1157
+ * @description Period the `salaryMin` and `salaryMax` figures are quoted against. Pass `null` to clear the stored value; omitted means unchanged.
1158
+ * @enum {string|null}
1152
1159
  */
1153
- salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour";
1160
+ salaryTimeframe?: "per_year" | "per_month" | "per_week" | "per_day" | "per_hour" | null;
1154
1161
  /** @description Up to 100 canonical skill slugs from `GET /v1/taxonomies/skills`. Every slug must exist in this account. */
1155
1162
  skills?: string[];
1156
1163
  /** @description Up to 100 canonical category slugs from `GET /v1/taxonomies/categories`. Every slug must exist in this account. */
@@ -1455,6 +1462,21 @@ interface components {
1455
1462
  /** @description Number of companies on the board in this market. */
1456
1463
  companyCount: number;
1457
1464
  };
1465
+ MarketingConsent: {
1466
+ id: string;
1467
+ /** @enum {string} */
1468
+ object: "marketing_consent";
1469
+ /** @enum {string} */
1470
+ status: "granted" | "withdrawn";
1471
+ source: string;
1472
+ /** @enum {string|null} */
1473
+ reason: "person_request" | "operator_request" | "account_deleted" | null;
1474
+ /** Format: date-time */
1475
+ grantedAt: string | null;
1476
+ /** Format: date-time */
1477
+ withdrawnAt: string | null;
1478
+ revision: number;
1479
+ } | null;
1458
1480
  Message: {
1459
1481
  id: string;
1460
1482
  /** @enum {string} */
@@ -1518,7 +1540,9 @@ interface components {
1518
1540
  /** @enum {string} */
1519
1541
  object: "plan";
1520
1542
  id: string;
1543
+ /** @description The operator's authoring-default plan name, in the board's language. Board templates that localize chrome should treat this as the fallback and word plan names from `featureSummary` structure or their own catalogs. */
1521
1544
  name: string;
1545
+ /** @description Authoring default: the operator's prose description in the board's language. The localized public string lives in the board template — compose it from `featureSummary`, `billingInterval`, and `talent` rather than displaying this verbatim on localized surfaces. */
1522
1546
  description: string | null;
1523
1547
  /** @enum {string} */
1524
1548
  purpose: "job_posting" | "talent_access";
@@ -1646,7 +1670,17 @@ interface components {
1646
1670
  name: string;
1647
1671
  /** @description Board language (ISO code); defaults to "en". */
1648
1672
  language: string;
1673
+ /** @description Absolute URL for the board logo, or null when unset. Operators set this under Settings → General (upload or logo generator); the website builder can manage it too. */
1649
1674
  logoUrl: string | null;
1675
+ /** @description Absolute URLs for the favicon / app-icon pack derived from the board logo (null when a variant is unset). Brand identity next to `logoUrl` — build `<link rel="icon">` tags and the web-manifest icon list from these. Not SEO infra (`board.seo()`). */
1676
+ icons: {
1677
+ ico: string | null;
1678
+ svg: string | null;
1679
+ appleTouch: string | null;
1680
+ icon192: string | null;
1681
+ icon512: string | null;
1682
+ iconMaskable512: string | null;
1683
+ };
1650
1684
  /** @description Active custom-domain hostname, or null. */
1651
1685
  primaryDomain: string | null;
1652
1686
  /** @description Whitelabel toggle (default `true`). Render the "Powered by Cavuno" badge unless `false`. */
@@ -1913,11 +1947,17 @@ interface components {
1913
1947
  remoteOption: "on_site" | "hybrid" | "remote" | null;
1914
1948
  /** @description Display region label for remote jobs (e.g. "United States", "Worldwide"); `null` for non-remote jobs. */
1915
1949
  remoteLocationLabel: string | null;
1950
+ /** @description Structured twin of `remoteLocationLabel`’s "Worldwide" case: `true` when the remote permit selection is unrestricted (explicit worldwide, or no constraint), `false` for a constrained remote job, `null` for non-remote jobs. Word it from your own catalog instead of matching the board-language label string. */
1951
+ remoteWorldwide: boolean | null;
1952
+ /** @description ISO 3166-1 alpha-2 codes the remote permit selection covers (derived expansion, mirroring the job detail field of the same name). Empty for worldwide/unconstrained and non-remote jobs. */
1953
+ remoteWorkPermitCountryCodes: string[];
1916
1954
  salaryMin: number | null;
1917
1955
  salaryMax: number | null;
1918
1956
  salaryCurrency: string | null;
1919
1957
  salaryTimeframe: string | null;
1920
1958
  isFeatured: boolean;
1959
+ /** @description Plain-text card teaser derived from the job description (HTML stripped, first sentence / word-boundary cut). `null` when there is nothing honest to show. Always present — independent of the `?fields=+description` opt-in for the long-form HTML body. Prefer this over requesting `+description` for list/card renders. */
1960
+ summary: string | null;
1921
1961
  locationLabel: string | null;
1922
1962
  /** @description Embedded company summary, or `null` if none is attached. */
1923
1963
  company: {
@@ -2380,6 +2420,12 @@ interface components {
2380
2420
  headline: string | null;
2381
2421
  location: string | null;
2382
2422
  avatarUrl: string | null;
2423
+ /** @description Plain-text card teaser derived from `bio` (HTML stripped, first sentence / word-boundary cut). `null` when there is nothing honest to show. Prefer this over `bio` for directory/card renders; cards still lead with `headline` when present. */
2424
+ summary: string | null;
2425
+ /**
2426
+ * @deprecated
2427
+ * @description Long-form candidate bio. **Deprecated on directory entries** — prefer `summary` for card teasers. Still the full prose on the talent profile detail (`GET …/talent/{handle}`).
2428
+ */
2383
2429
  bio: string | null;
2384
2430
  jobSearchStatus: string | null;
2385
2431
  skills: string[];
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-GVe6WAfT.js';
1
+ import { S as Schemas } from './_spec-BnoxU-iR.js';
2
2
 
3
3
  /** Author shape embedded on posts (no `object` discriminator). */
4
4
  type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-GVe6WAfT.mjs';
1
+ import { S as Schemas } from './_spec-BnoxU-iR.mjs';
2
2
 
3
3
  /** Author shape embedded on posts (no `object` discriminator). */
4
4
  type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
@@ -1,5 +1,5 @@
1
- import { S as Schemas } from './_spec-GVe6WAfT.js';
2
- import { L as ListEnvelope, m as RelatedSearch } from './jobs-QrbXOYB9.js';
1
+ import { S as Schemas } from './_spec-BnoxU-iR.js';
2
+ import { L as ListEnvelope, m as RelatedSearch } from './jobs-B8DNWEir.js';
3
3
 
4
4
  type PublicCompany = Schemas['CompanyPublic'];
5
5
  /** A market (sector) a company operates in — name + its source slug. */
@@ -1,5 +1,5 @@
1
- import { S as Schemas } from './_spec-GVe6WAfT.mjs';
2
- import { L as ListEnvelope, m as RelatedSearch } from './jobs-BuLpV8iy.mjs';
1
+ import { S as Schemas } from './_spec-BnoxU-iR.mjs';
2
+ import { L as ListEnvelope, m as RelatedSearch } from './jobs-aTp9uC3a.mjs';
3
3
 
4
4
  type PublicCompany = Schemas['CompanyPublic'];
5
5
  /** A market (sector) a company operates in — name + its source slug. */
@@ -1,5 +1,5 @@
1
- import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-DUhgiacm.js';
2
- import { P as PublicJob } from './jobs-QrbXOYB9.js';
1
+ import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-4vXzYDL3.js';
2
+ import { P as PublicJob } from './jobs-B8DNWEir.js';
3
3
 
4
4
  /**
5
5
  * Wire enum for `salaryTimeframe`. Defined here (not re-exported from any
@@ -1,5 +1,5 @@
1
- import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-GGWJ4coe.mjs';
2
- import { P as PublicJob } from './jobs-BuLpV8iy.mjs';
1
+ import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-CvBkK7my.mjs';
2
+ import { P as PublicJob } from './jobs-aTp9uC3a.mjs';
3
3
 
4
4
  /**
5
5
  * Wire enum for `salaryTimeframe`. Defined here (not re-exported from any
@@ -1,5 +1,5 @@
1
- import { J as JobSort, E as EmploymentType, R as RemoteOption, S as Seniority } from './jobs-BuLpV8iy.mjs';
2
- import './_spec-GVe6WAfT.mjs';
1
+ import { J as JobSort, E as EmploymentType, R as RemoteOption, S as Seniority } from './jobs-aTp9uC3a.mjs';
2
+ import './_spec-BnoxU-iR.mjs';
3
3
 
4
4
  /**
5
5
  * `@cavuno/board/filters` — the canonical listing-filter vocabulary and URL
package/dist/filters.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { J as JobSort, E as EmploymentType, R as RemoteOption, S as Seniority } from './jobs-QrbXOYB9.js';
2
- import './_spec-GVe6WAfT.js';
1
+ import { J as JobSort, E as EmploymentType, R as RemoteOption, S as Seniority } from './jobs-B8DNWEir.js';
2
+ import './_spec-BnoxU-iR.js';
3
3
 
4
4
  /**
5
5
  * `@cavuno/board/filters` — the canonical listing-filter vocabulary and URL
package/dist/format.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- export { C as CurrencyDisplay, F as FormattedSalaryRange, J as JobBreadcrumb, N as NumberNotation, S as SalaryTimeframeInput, a as SalaryTimeframeValue, b as buildJobBreadcrumbs, f as formatSalaryRange, c as formatSalaryStat, d as formatSalaryStatRange, n as normalizeWebsiteUrl } from './breadcrumbs-DFKr0HzU.mjs';
2
- import { C as CustomFieldDefinition } from './board-GGWJ4coe.mjs';
3
- import { C as CustomFieldValues } from './jobs-BuLpV8iy.mjs';
4
- import './_spec-GVe6WAfT.mjs';
1
+ export { C as CurrencyDisplay, F as FormattedSalaryRange, J as JobBreadcrumb, N as NumberNotation, S as SalaryTimeframeInput, a as SalaryTimeframeValue, b as buildJobBreadcrumbs, f as formatSalaryRange, c as formatSalaryStat, d as formatSalaryStatRange, n as normalizeWebsiteUrl } from './breadcrumbs-Cz1sFqtV.mjs';
2
+ import { C as CustomFieldDefinition } from './board-CvBkK7my.mjs';
3
+ import { C as CustomFieldValues } from './jobs-aTp9uC3a.mjs';
4
+ import './_spec-BnoxU-iR.mjs';
5
5
 
6
6
  /**
7
7
  * Date display helpers in the board language (required leading parameter,
package/dist/format.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { C as CurrencyDisplay, F as FormattedSalaryRange, J as JobBreadcrumb, N as NumberNotation, S as SalaryTimeframeInput, a as SalaryTimeframeValue, b as buildJobBreadcrumbs, f as formatSalaryRange, c as formatSalaryStat, d as formatSalaryStatRange, n as normalizeWebsiteUrl } from './breadcrumbs-DiccJhk4.js';
2
- import { C as CustomFieldDefinition } from './board-DUhgiacm.js';
3
- import { C as CustomFieldValues } from './jobs-QrbXOYB9.js';
4
- import './_spec-GVe6WAfT.js';
1
+ export { C as CurrencyDisplay, F as FormattedSalaryRange, J as JobBreadcrumb, N as NumberNotation, S as SalaryTimeframeInput, a as SalaryTimeframeValue, b as buildJobBreadcrumbs, f as formatSalaryRange, c as formatSalaryStat, d as formatSalaryStatRange, n as normalizeWebsiteUrl } from './breadcrumbs-Blf_rsux.js';
2
+ import { C as CustomFieldDefinition } from './board-4vXzYDL3.js';
3
+ import { C as CustomFieldValues } from './jobs-B8DNWEir.js';
4
+ import './_spec-BnoxU-iR.js';
5
5
 
6
6
  /**
7
7
  * Date display helpers in the board language (required leading parameter,