@cavuno/board 4.4.1 → 4.6.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 (42) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/{_spec-COlkrizX.d.mts → _spec-Dm-1AieO.d.mts} +61 -1
  3. package/dist/{_spec-COlkrizX.d.ts → _spec-Dm-1AieO.d.ts} +61 -1
  4. package/dist/{blog-CgA_ljHa.d.ts → blog-BvyEW4bf.d.ts} +1 -1
  5. package/dist/{blog-DO8Yn21_.d.mts → blog-C5g0Tt8w.d.mts} +1 -1
  6. package/dist/{board-D51C3gB5.d.ts → board-CW3qMKdu.d.ts} +2 -2
  7. package/dist/{board-JgFR-2UW.d.mts → board-CemD1yEl.d.mts} +2 -2
  8. package/dist/{breadcrumbs-_QzN4nEk.d.ts → breadcrumbs-BRHiWWSf.d.ts} +2 -2
  9. package/dist/{breadcrumbs-zAN2biAq.d.mts → breadcrumbs-Bgmklae3.d.mts} +2 -2
  10. package/dist/browser/cavuno-board.global.min.js +1 -1
  11. package/dist/{chunk-2ETP5UH4.mjs → chunk-GC5QWN7Y.mjs} +16 -0
  12. package/dist/{chunk-YEAQ3JEI.mjs → chunk-VWGF4I5C.mjs} +143 -4
  13. package/dist/filters.d.mts +2 -2
  14. package/dist/filters.d.ts +2 -2
  15. package/dist/format.d.mts +4 -4
  16. package/dist/format.d.ts +4 -4
  17. package/dist/format.js +15 -2
  18. package/dist/format.mjs +2 -126
  19. package/dist/index.d.mts +89 -12
  20. package/dist/index.d.ts +89 -12
  21. package/dist/index.js +205 -1
  22. package/dist/index.mjs +190 -2
  23. package/dist/{jobs-C1Mxty1n.d.mts → jobs-B0phTsdB.d.mts} +1 -1
  24. package/dist/{jobs-DOF3QXdq.d.ts → jobs-f-n4_rrz.d.ts} +1 -1
  25. package/dist/{search-_QDaN6Um.d.ts → search-C1LHejWz.d.ts} +1 -1
  26. package/dist/{search-Cx_dsVUb.d.mts → search-DVg1L-3s.d.mts} +1 -1
  27. package/dist/seo.d.mts +6 -6
  28. package/dist/seo.d.ts +6 -6
  29. package/dist/seo.js +16 -1
  30. package/dist/seo.mjs +1 -1
  31. package/dist/server.d.mts +5 -5
  32. package/dist/server.d.ts +5 -5
  33. package/dist/server.mjs +1 -1
  34. package/dist/sitemap.d.mts +5 -5
  35. package/dist/sitemap.d.ts +5 -5
  36. package/dist/suggest.d.mts +2 -2
  37. package/dist/suggest.d.ts +2 -2
  38. package/package.json +1 -1
  39. package/skills/cavuno-board-account/SKILL.md +31 -2
  40. package/skills/cavuno-board-companies/SKILL.md +21 -0
  41. package/skills/cavuno-board-seo/SALARY.md +2 -1
  42. package/skills/manifest.json +2 -2
package/CHANGELOG.md CHANGED
@@ -3,6 +3,37 @@
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.6.0 — 2026-08-22
7
+
8
+ - **`board.me.recommendedJobs.list`**: personalized jobs for the signed-in
9
+ candidate, best match first. Each item wraps the same slim `job_card` the
10
+ jobs list returns. The response never includes scores, weights, or ranker
11
+ identity. Empty list means there is no usable profile signal yet — drive a
12
+ resume-upload CTA from `board.me.profile` / `board.me.resume`. Exported
13
+ types: `RecommendedJob`, `RecommendedJobsListQuery`. Documented in the
14
+ account skill and [How to show job matches](https://cavuno.com/docs/sdk/cookbook/recommended-jobs).
15
+
16
+ ## 4.5.0 — 2026-08-21
17
+
18
+ - **Board-user account self-service**: signed-in board users manage their own
19
+ account over the API. New `board.me` verbs and `/v1/boards/{identifier}/me/*`
20
+ endpoints: `updatePassword`, `requestEmailChange` / `confirmEmailChange`
21
+ (verify-then-switch), and account deletion. The `board_user` resource now
22
+ exposes `hasPassword` so headless frontends can decide between change-password
23
+ and set-password flows.
24
+ - **Company team management**: `board.me.companies` gains members and invites —
25
+ list members, change a member's role (`admin` / `member`), remove a member,
26
+ create / list / revoke email invites (7-day links), accept an invite, and
27
+ `leave(slug)` (`DELETE .../me/companies/{slug}/membership`). A company always
28
+ keeps at least one admin: the API answers `409 last_admin` when an action
29
+ would strand it.
30
+ - **Analytics**: apply-clicks and job-visitors reporting can group by
31
+ first-touch channel, and apply-click rows carry `jobSlug`.
32
+ - **Company blocklist**: endpoints for blocking a company from automated
33
+ sourcing so imports and aggregation cannot reintroduce it.
34
+ - **Fix**: salary formatting falls back cleanly when the runtime lacks
35
+ `Intl.NumberFormat.formatRange`.
36
+
6
37
  ## 4.4.1 — 2026-08-10
7
38
 
8
39
  - **SDK installation documentation**: The npm and GitHub README now presents
@@ -1,5 +1,8 @@
1
1
  interface components {
2
2
  schemas: {
3
+ AcceptCompanyMemberInviteBody: {
4
+ token: string;
5
+ };
3
6
  AccessCheckoutBody: {
4
7
  /**
5
8
  * @description The offer tier to purchase (from `GET /paywall/offers/enabled`).
@@ -262,6 +265,8 @@ interface components {
262
265
  email: string;
263
266
  displayName: string | null;
264
267
  emailVerified: boolean;
268
+ /** @description Whether the account has a password credential. False for OAuth/magic-link-only accounts; frontends use it to offer change-password vs set-password (the set flow is POST /auth/forgot-password). */
269
+ hasPassword: boolean;
265
270
  };
266
271
  BulkMoveApplicantsBody: {
267
272
  applicationIds: string[];
@@ -404,6 +409,34 @@ interface components {
404
409
  /** @description Source slug for the market. Use it as the `:market` segment of the market-scoped company browse. */
405
410
  slug: string;
406
411
  };
412
+ CompanyMember: {
413
+ id: string;
414
+ /** @enum {string} */
415
+ object: "company_member";
416
+ boardUserId: string;
417
+ displayName: string | null;
418
+ email: string;
419
+ /** @enum {string} */
420
+ role: "admin" | "member";
421
+ approvedBy: string | null;
422
+ /** Format: date-time */
423
+ createdAt: string;
424
+ };
425
+ CompanyMemberInvite: {
426
+ id: string;
427
+ /** @enum {string} */
428
+ object: "company_member_invite";
429
+ email: string;
430
+ /** Format: date-time */
431
+ createdAt: string;
432
+ /** Format: date-time */
433
+ expiresAt: string;
434
+ };
435
+ CompanyMemberInviteAcceptance: {
436
+ /** @enum {string} */
437
+ object: "company_member_invite_acceptance";
438
+ companySlug: string;
439
+ };
407
440
  CompanyMembership: {
408
441
  id: string;
409
442
  /** @enum {string} */
@@ -558,6 +591,9 @@ interface components {
558
591
  /** @description Live published-job count for this company on the board. */
559
592
  jobCount: number;
560
593
  };
594
+ ConfirmEmailChangeBody: {
595
+ token: string;
596
+ };
561
597
  ConfirmWorkEmailBody: {
562
598
  token: string;
563
599
  };
@@ -618,6 +654,10 @@ interface components {
618
654
  /** @description URL-friendly slug for the company. Auto-generated from `name` when omitted. */
619
655
  slug?: string;
620
656
  };
657
+ CreateCompanyMemberInviteBody: {
658
+ /** Format: email */
659
+ email: string;
660
+ };
621
661
  CreateEducationBody: {
622
662
  institutionName: string;
623
663
  institutionUrl?: string;
@@ -1973,7 +2013,7 @@ interface components {
1973
2013
  remoteOption: "on_site" | "hybrid" | "remote" | null;
1974
2014
  /** @description Display region label for remote jobs (e.g. "United States", "Worldwide"); `null` for non-remote jobs. */
1975
2015
  remoteLocationLabel: string | null;
1976
- /** @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. */
2016
+ /** @description Structured twin of `remoteLocationLabel`’s "Worldwide" case: `true` when the job explicitly declares an unrestricted (worldwide) permit, `false` for a constrained remote job, `null` when the job declares no remote scope at all AND for non-remote jobs. A job that declares nothing is unknown, not worldwide — do not treat `null` as unrestricted. Word it from your own catalog instead of matching the board-language label string. */
1977
2017
  remoteWorldwide: boolean | null;
1978
2018
  /** @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. */
1979
2019
  remoteWorkPermitCountryCodes: string[];
@@ -1982,6 +2022,8 @@ interface components {
1982
2022
  salaryCurrency: string | null;
1983
2023
  salaryTimeframe: string | null;
1984
2024
  isFeatured: boolean;
2025
+ /** @description True when this listing is a Forager CPC / partner-feed ad persisted on the board. */
2026
+ isSponsored: boolean;
1985
2027
  /** @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. */
1986
2028
  summary: string | null;
1987
2029
  locationLabel: string | null;
@@ -2125,6 +2167,11 @@ interface components {
2125
2167
  /** Format: date-time */
2126
2168
  markedAt: string;
2127
2169
  };
2170
+ RecommendedJob: {
2171
+ /** @enum {string} */
2172
+ object: "recommended_job";
2173
+ job: components["schemas"]["PublicJobCard"];
2174
+ };
2128
2175
  RedirectResolution: {
2129
2176
  /** @enum {string} */
2130
2177
  object: "redirect_resolution";
@@ -2154,6 +2201,10 @@ interface components {
2154
2201
  reason: "spam" | "harassment" | "misrepresentation" | "other";
2155
2202
  freeText?: string;
2156
2203
  };
2204
+ RequestEmailChangeBody: {
2205
+ /** Format: email */
2206
+ email: string;
2207
+ };
2157
2208
  Resume: {
2158
2209
  /** @enum {string} */
2159
2210
  object: "resume";
@@ -2730,6 +2781,10 @@ interface components {
2730
2781
  jobSearchStatusVisibleTo?: "everyone" | "employers_only";
2731
2782
  openToRelocate?: boolean;
2732
2783
  };
2784
+ UpdateCompanyMemberRoleBody: {
2785
+ /** @enum {string} */
2786
+ role: "admin" | "member";
2787
+ };
2733
2788
  UpdateEducationBody: {
2734
2789
  institutionName?: string;
2735
2790
  institutionUrl?: string;
@@ -2775,6 +2830,11 @@ interface components {
2775
2830
  channel: "messageEmails" | "applicationEmails";
2776
2831
  subscribed: boolean;
2777
2832
  };
2833
+ UpdatePasswordBody: {
2834
+ currentPassword: string;
2835
+ /** @description Minimum 8 characters. */
2836
+ newPassword: string;
2837
+ };
2778
2838
  UpdatePipelineStageBody: {
2779
2839
  label?: string;
2780
2840
  hidden?: boolean;
@@ -1,5 +1,8 @@
1
1
  interface components {
2
2
  schemas: {
3
+ AcceptCompanyMemberInviteBody: {
4
+ token: string;
5
+ };
3
6
  AccessCheckoutBody: {
4
7
  /**
5
8
  * @description The offer tier to purchase (from `GET /paywall/offers/enabled`).
@@ -262,6 +265,8 @@ interface components {
262
265
  email: string;
263
266
  displayName: string | null;
264
267
  emailVerified: boolean;
268
+ /** @description Whether the account has a password credential. False for OAuth/magic-link-only accounts; frontends use it to offer change-password vs set-password (the set flow is POST /auth/forgot-password). */
269
+ hasPassword: boolean;
265
270
  };
266
271
  BulkMoveApplicantsBody: {
267
272
  applicationIds: string[];
@@ -404,6 +409,34 @@ interface components {
404
409
  /** @description Source slug for the market. Use it as the `:market` segment of the market-scoped company browse. */
405
410
  slug: string;
406
411
  };
412
+ CompanyMember: {
413
+ id: string;
414
+ /** @enum {string} */
415
+ object: "company_member";
416
+ boardUserId: string;
417
+ displayName: string | null;
418
+ email: string;
419
+ /** @enum {string} */
420
+ role: "admin" | "member";
421
+ approvedBy: string | null;
422
+ /** Format: date-time */
423
+ createdAt: string;
424
+ };
425
+ CompanyMemberInvite: {
426
+ id: string;
427
+ /** @enum {string} */
428
+ object: "company_member_invite";
429
+ email: string;
430
+ /** Format: date-time */
431
+ createdAt: string;
432
+ /** Format: date-time */
433
+ expiresAt: string;
434
+ };
435
+ CompanyMemberInviteAcceptance: {
436
+ /** @enum {string} */
437
+ object: "company_member_invite_acceptance";
438
+ companySlug: string;
439
+ };
407
440
  CompanyMembership: {
408
441
  id: string;
409
442
  /** @enum {string} */
@@ -558,6 +591,9 @@ interface components {
558
591
  /** @description Live published-job count for this company on the board. */
559
592
  jobCount: number;
560
593
  };
594
+ ConfirmEmailChangeBody: {
595
+ token: string;
596
+ };
561
597
  ConfirmWorkEmailBody: {
562
598
  token: string;
563
599
  };
@@ -618,6 +654,10 @@ interface components {
618
654
  /** @description URL-friendly slug for the company. Auto-generated from `name` when omitted. */
619
655
  slug?: string;
620
656
  };
657
+ CreateCompanyMemberInviteBody: {
658
+ /** Format: email */
659
+ email: string;
660
+ };
621
661
  CreateEducationBody: {
622
662
  institutionName: string;
623
663
  institutionUrl?: string;
@@ -1973,7 +2013,7 @@ interface components {
1973
2013
  remoteOption: "on_site" | "hybrid" | "remote" | null;
1974
2014
  /** @description Display region label for remote jobs (e.g. "United States", "Worldwide"); `null` for non-remote jobs. */
1975
2015
  remoteLocationLabel: string | null;
1976
- /** @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. */
2016
+ /** @description Structured twin of `remoteLocationLabel`’s "Worldwide" case: `true` when the job explicitly declares an unrestricted (worldwide) permit, `false` for a constrained remote job, `null` when the job declares no remote scope at all AND for non-remote jobs. A job that declares nothing is unknown, not worldwide — do not treat `null` as unrestricted. Word it from your own catalog instead of matching the board-language label string. */
1977
2017
  remoteWorldwide: boolean | null;
1978
2018
  /** @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. */
1979
2019
  remoteWorkPermitCountryCodes: string[];
@@ -1982,6 +2022,8 @@ interface components {
1982
2022
  salaryCurrency: string | null;
1983
2023
  salaryTimeframe: string | null;
1984
2024
  isFeatured: boolean;
2025
+ /** @description True when this listing is a Forager CPC / partner-feed ad persisted on the board. */
2026
+ isSponsored: boolean;
1985
2027
  /** @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. */
1986
2028
  summary: string | null;
1987
2029
  locationLabel: string | null;
@@ -2125,6 +2167,11 @@ interface components {
2125
2167
  /** Format: date-time */
2126
2168
  markedAt: string;
2127
2169
  };
2170
+ RecommendedJob: {
2171
+ /** @enum {string} */
2172
+ object: "recommended_job";
2173
+ job: components["schemas"]["PublicJobCard"];
2174
+ };
2128
2175
  RedirectResolution: {
2129
2176
  /** @enum {string} */
2130
2177
  object: "redirect_resolution";
@@ -2154,6 +2201,10 @@ interface components {
2154
2201
  reason: "spam" | "harassment" | "misrepresentation" | "other";
2155
2202
  freeText?: string;
2156
2203
  };
2204
+ RequestEmailChangeBody: {
2205
+ /** Format: email */
2206
+ email: string;
2207
+ };
2157
2208
  Resume: {
2158
2209
  /** @enum {string} */
2159
2210
  object: "resume";
@@ -2730,6 +2781,10 @@ interface components {
2730
2781
  jobSearchStatusVisibleTo?: "everyone" | "employers_only";
2731
2782
  openToRelocate?: boolean;
2732
2783
  };
2784
+ UpdateCompanyMemberRoleBody: {
2785
+ /** @enum {string} */
2786
+ role: "admin" | "member";
2787
+ };
2733
2788
  UpdateEducationBody: {
2734
2789
  institutionName?: string;
2735
2790
  institutionUrl?: string;
@@ -2775,6 +2830,11 @@ interface components {
2775
2830
  channel: "messageEmails" | "applicationEmails";
2776
2831
  subscribed: boolean;
2777
2832
  };
2833
+ UpdatePasswordBody: {
2834
+ currentPassword: string;
2835
+ /** @description Minimum 8 characters. */
2836
+ newPassword: string;
2837
+ };
2778
2838
  UpdatePipelineStageBody: {
2779
2839
  label?: string;
2780
2840
  hidden?: boolean;
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-COlkrizX.js';
1
+ import { S as Schemas } from './_spec-Dm-1AieO.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-COlkrizX.mjs';
1
+ import { S as Schemas } from './_spec-Dm-1AieO.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-COlkrizX.js';
2
- import { L as ListEnvelope, m as RelatedSearch } from './jobs-DOF3QXdq.js';
1
+ import { S as Schemas } from './_spec-Dm-1AieO.js';
2
+ import { L as ListEnvelope, m as RelatedSearch } from './jobs-f-n4_rrz.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-COlkrizX.mjs';
2
- import { L as ListEnvelope, m as RelatedSearch } from './jobs-C1Mxty1n.mjs';
1
+ import { S as Schemas } from './_spec-Dm-1AieO.mjs';
2
+ import { L as ListEnvelope, m as RelatedSearch } from './jobs-B0phTsdB.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-D51C3gB5.js';
2
- import { P as PublicJob } from './jobs-DOF3QXdq.js';
1
+ import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-CW3qMKdu.js';
2
+ import { P as PublicJob } from './jobs-f-n4_rrz.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-JgFR-2UW.mjs';
2
- import { P as PublicJob } from './jobs-C1Mxty1n.mjs';
1
+ import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-CemD1yEl.mjs';
2
+ import { P as PublicJob } from './jobs-B0phTsdB.mjs';
3
3
 
4
4
  /**
5
5
  * Wire enum for `salaryTimeframe`. Defined here (not re-exported from any