@cavuno/board 1.39.0 → 1.41.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 (37) hide show
  1. package/dist/{_spec-DxC1ze93.d.mts → _spec-l_596ZwW.d.mts} +373 -0
  2. package/dist/{_spec-DxC1ze93.d.ts → _spec-l_596ZwW.d.ts} +373 -0
  3. package/dist/bin.mjs +242 -18
  4. package/dist/{board-RfZEAJse.d.ts → board-BzK5j73O.d.ts} +1 -1
  5. package/dist/{board-CqYibYUA.d.mts → board-CyHA6rRP.d.mts} +1 -1
  6. package/dist/doctor.js +238 -14
  7. package/dist/doctor.mjs +238 -14
  8. package/dist/filters.d.mts +2 -2
  9. package/dist/filters.d.ts +2 -2
  10. package/dist/format.d.mts +3 -3
  11. package/dist/format.d.ts +3 -3
  12. package/dist/index.d.mts +89 -10
  13. package/dist/index.d.ts +89 -10
  14. package/dist/index.js +91 -1
  15. package/dist/index.mjs +91 -1
  16. package/dist/{jobs-DPPA1Nev.d.mts → jobs-BhthvMkA.d.mts} +1 -1
  17. package/dist/{jobs-CLLIvtMc.d.ts → jobs-CXudz1Y4.d.ts} +1 -1
  18. package/dist/{salaries-DK4RnJnw.d.ts → salaries-ByBuHCLH.d.ts} +2 -2
  19. package/dist/{salaries-Rb5h_eVZ.d.mts → salaries-Dr_Zugal.d.mts} +2 -2
  20. package/dist/{search-CqBa1Qc4.d.mts → search-CrIlXSJP.d.mts} +1 -1
  21. package/dist/{search-DBoMM-gE.d.ts → search-DZrq-k76.d.ts} +1 -1
  22. package/dist/seo.d.mts +4 -4
  23. package/dist/seo.d.ts +4 -4
  24. package/dist/server.d.mts +56 -6
  25. package/dist/server.d.ts +56 -6
  26. package/dist/server.js +41 -0
  27. package/dist/server.mjs +41 -0
  28. package/dist/sitemap.d.mts +5 -5
  29. package/dist/sitemap.d.ts +5 -5
  30. package/dist/suggest.d.mts +2 -2
  31. package/dist/suggest.d.ts +2 -2
  32. package/dist/theme.d.mts +49 -1
  33. package/dist/theme.d.ts +49 -1
  34. package/dist/theme.js +60 -26
  35. package/dist/theme.mjs +60 -26
  36. package/package.json +1 -1
  37. package/skills/manifest.json +1 -1
package/dist/doctor.mjs CHANGED
@@ -102,6 +102,156 @@ function summarize(results) {
102
102
  return { exitCode: failed.length > 0 ? 1 : 0, passed, failed, skipped };
103
103
  }
104
104
 
105
+ // src/doctor/cookie-conformance.ts
106
+ import { existsSync, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
107
+ import { join, relative } from "path";
108
+ var COOKIE = record("static.cookie-codec", 1);
109
+ var SOURCE_EXT = /\.(ts|tsx|js|jsx|mjs|cjs|astro|svelte|vue)$/;
110
+ var REMEDIATION = "set cookies only through the SDK server cookie codec (buildCookie/buildClearCookie from @cavuno/board/server)";
111
+ var SET_COOKIE_SINK = /set-cookie/i;
112
+ var DOCUMENT_COOKIE_ASSIGN = /document\.cookie\s*\+?=(?!=)/i;
113
+ var DOMAIN_SCOPE = /domain\s*=/i;
114
+ var LOOKAHEAD_LINES = 3;
115
+ function stripComments(line) {
116
+ let out = "";
117
+ let i = 0;
118
+ let quote = null;
119
+ while (i < line.length) {
120
+ const c = line[i];
121
+ if (quote !== null) {
122
+ out += c;
123
+ if (c === "\\" && i + 1 < line.length) {
124
+ out += line[i + 1];
125
+ i += 2;
126
+ continue;
127
+ }
128
+ if (c === quote) quote = null;
129
+ i += 1;
130
+ continue;
131
+ }
132
+ if (c === "'" || c === '"' || c === "`") {
133
+ quote = c;
134
+ out += c;
135
+ i += 1;
136
+ continue;
137
+ }
138
+ if (c === "/" && i + 1 < line.length && line[i - 1] !== "\\") {
139
+ const next = line[i + 1];
140
+ if (next === "/") {
141
+ break;
142
+ }
143
+ if (next === "*") {
144
+ i += 2;
145
+ while (i < line.length) {
146
+ if (line[i] === "*" && i + 1 < line.length && line[i + 1] === "/") {
147
+ i += 2;
148
+ break;
149
+ }
150
+ i += 1;
151
+ }
152
+ continue;
153
+ }
154
+ }
155
+ out += c;
156
+ i += 1;
157
+ }
158
+ return out;
159
+ }
160
+ function isCommentLine(line) {
161
+ const trimmed = line.trim();
162
+ if (trimmed.startsWith("*")) return true;
163
+ return stripComments(line).trim() === "";
164
+ }
165
+ function hasCookieWriteSink(line) {
166
+ return SET_COOKIE_SINK.test(line) || DOCUMENT_COOKIE_ASSIGN.test(line);
167
+ }
168
+ function statementWindow(lines, sinkIdx) {
169
+ const sinkStripped = stripComments(lines[sinkIdx]);
170
+ const parts = [sinkStripped];
171
+ if (sinkStripped.includes(";")) return sinkStripped;
172
+ let taken = 0;
173
+ for (let j = sinkIdx + 1; j < lines.length && taken < LOOKAHEAD_LINES; j += 1) {
174
+ const next = lines[j];
175
+ if (isCommentLine(next)) continue;
176
+ const stripped = stripComments(next);
177
+ parts.push(stripped);
178
+ taken += 1;
179
+ if (stripped.includes(";")) break;
180
+ }
181
+ return parts.join("\n");
182
+ }
183
+ function isOffendingSink(lines, index) {
184
+ const line = lines[index];
185
+ if (isCommentLine(line)) return false;
186
+ const stripped = stripComments(line);
187
+ if (!hasCookieWriteSink(stripped)) return false;
188
+ return DOMAIN_SCOPE.test(statementWindow(lines, index));
189
+ }
190
+ function walkSourceFiles(dir, out) {
191
+ let entries;
192
+ try {
193
+ entries = readdirSync(dir);
194
+ } catch {
195
+ return;
196
+ }
197
+ for (const name of entries) {
198
+ if (name === "node_modules" || name.startsWith(".")) continue;
199
+ const full = join(dir, name);
200
+ let st;
201
+ try {
202
+ st = statSync(full);
203
+ } catch {
204
+ continue;
205
+ }
206
+ if (st.isDirectory()) {
207
+ walkSourceFiles(full, out);
208
+ } else if (st.isFile() && SOURCE_EXT.test(name)) {
209
+ out.push(full);
210
+ }
211
+ }
212
+ }
213
+ function truncate(line, max = 120) {
214
+ const t = line.trim();
215
+ return t.length > max ? `${t.slice(0, max)}\u2026` : t;
216
+ }
217
+ function checkCookieCodecConformance(projectRoot) {
218
+ const srcDir = join(projectRoot, "src");
219
+ if (!existsSync(srcDir)) {
220
+ return [
221
+ COOKIE(
222
+ "skip",
223
+ "no src/ directory \u2014 cookie-codec conformance scan skipped"
224
+ )
225
+ ];
226
+ }
227
+ const files = [];
228
+ walkSourceFiles(srcDir, files);
229
+ const findings = [];
230
+ for (const file of files) {
231
+ const rel = relative(projectRoot, file).split("\\").join("/");
232
+ let text;
233
+ try {
234
+ text = readFileSync2(file, "utf8");
235
+ } catch {
236
+ continue;
237
+ }
238
+ const lines = text.split(/\r?\n/);
239
+ for (let i = 0; i < lines.length; i += 1) {
240
+ if (!isOffendingSink(lines, i)) continue;
241
+ findings.push(`${rel}:${i + 1} \u2014 ${truncate(lines[i])}`);
242
+ }
243
+ }
244
+ if (findings.length === 0) {
245
+ return [
246
+ COOKIE(
247
+ "pass",
248
+ "no domain-scoped Set-Cookie or document.cookie writes in src/"
249
+ )
250
+ ];
251
+ }
252
+ return [COOKIE("fail", `${findings.join("; ")}; ${REMEDIATION}`)];
253
+ }
254
+
105
255
  // src/doctor/probe.ts
106
256
  var FETCH_TIMEOUT_MS = 1e4;
107
257
  async function probe(fetchImpl, url) {
@@ -221,14 +371,82 @@ async function runReadProbes(fetchImpl, frontendUrl) {
221
371
  ];
222
372
  }
223
373
 
374
+ // src/doctor/sandbox.ts
375
+ var SANDBOX_GATE = record("sandbox.persona-gate", 1);
376
+ var EXPECTED_PERSONA_COUNT = 8;
377
+ function skipSandboxPersonaGate(reason) {
378
+ return SANDBOX_GATE("skip", reason);
379
+ }
380
+ async function checkSandboxPersonaGate(fetchImpl, env, boardContext) {
381
+ if (boardContext === null) {
382
+ return SANDBOX_GATE(
383
+ "skip",
384
+ "board did not resolve \u2014 fix static.board first"
385
+ );
386
+ }
387
+ const url = `${apiBase(env.apiUrl)}/v1/boards/${encodeURIComponent(env.boardKey)}/sandbox/personas`;
388
+ const result = await probe(fetchImpl, url);
389
+ if (boardContext.sandbox !== true) {
390
+ return result.status === 404 ? SANDBOX_GATE(
391
+ "pass",
392
+ "sandbox persona endpoint refuses (404) on a non-sandbox board"
393
+ ) : SANDBOX_GATE(
394
+ "fail",
395
+ `sandbox persona endpoint is reachable on a NON-sandbox board (HTTP ${result.status}) \u2014 the capability gate is not holding`
396
+ );
397
+ }
398
+ if (!result.ok) {
399
+ return SANDBOX_GATE(
400
+ "fail",
401
+ `sandbox persona roster did not resolve (HTTP ${result.status}) \u2014 the persona seed may have failed`
402
+ );
403
+ }
404
+ let personas;
405
+ let password;
406
+ try {
407
+ const parsed = JSON.parse(result.body);
408
+ personas = parsed.personas;
409
+ password = parsed.password;
410
+ } catch {
411
+ return SANDBOX_GATE(
412
+ "fail",
413
+ "sandbox persona endpoint returned 200 but not JSON \u2014 proxy or captive portal in the way?"
414
+ );
415
+ }
416
+ if (!Array.isArray(personas) || personas.length !== EXPECTED_PERSONA_COUNT) {
417
+ return SANDBOX_GATE(
418
+ "fail",
419
+ `expected ${EXPECTED_PERSONA_COUNT} personas, got ${Array.isArray(personas) ? personas.length : "a non-array"} \u2014 the persona seed is incomplete`
420
+ );
421
+ }
422
+ const unseeded = personas.filter((persona) => persona.seeded !== true);
423
+ if (unseeded.length > 0) {
424
+ const ids = unseeded.map((persona) => typeof persona.id === "string" ? persona.id : "?").join(", ");
425
+ return SANDBOX_GATE(
426
+ "fail",
427
+ `${unseeded.length} of ${EXPECTED_PERSONA_COUNT} personas are not seeded on the board (${ids}) \u2014 the persona seed failed or was purged; run POST /v1/boards/{key}/sandbox/reseed to restore the roster`
428
+ );
429
+ }
430
+ if (typeof password !== "string" || password.length === 0) {
431
+ return SANDBOX_GATE(
432
+ "fail",
433
+ "roster present but the published password is missing"
434
+ );
435
+ }
436
+ return SANDBOX_GATE(
437
+ "pass",
438
+ `sandbox roster complete and seeded (${EXPECTED_PERSONA_COUNT} personas)`
439
+ );
440
+ }
441
+
224
442
  // src/doctor/theme.ts
225
443
  import { createHash } from "crypto";
226
- import { existsSync, readFileSync as readFileSync2 } from "fs";
227
- import { join } from "path";
444
+ import { existsSync as existsSync2, readFileSync as readFileSync3 } from "fs";
445
+ import { join as join2 } from "path";
228
446
  var THEME = record("static.theme", 1);
229
447
  function checkThemeFreshness(projectRoot, context) {
230
- const tokensPath = join(projectRoot, "src/tokens.css");
231
- if (!existsSync(tokensPath)) {
448
+ const tokensPath = join2(projectRoot, "src/tokens.css");
449
+ if (!existsSync2(tokensPath)) {
232
450
  return [
233
451
  THEME(
234
452
  "skip",
@@ -236,9 +454,9 @@ function checkThemeFreshness(projectRoot, context) {
236
454
  )
237
455
  ];
238
456
  }
239
- const tokensHash = createHash("sha256").update(readFileSync2(tokensPath, "utf8"), "utf8").digest("hex");
240
- const resolvedPath = join(projectRoot, "src/theme/resolved.ts");
241
- const resolvedHash = existsSync(resolvedPath) ? readFileSync2(resolvedPath, "utf8").match(
457
+ const tokensHash = createHash("sha256").update(readFileSync3(tokensPath, "utf8"), "utf8").digest("hex");
458
+ const resolvedPath = join2(projectRoot, "src/theme/resolved.ts");
459
+ const resolvedHash = existsSync2(resolvedPath) ? readFileSync3(resolvedPath, "utf8").match(
242
460
  /tokensHash = '([0-9a-f]{64})'/
243
461
  )?.[1] ?? null : null;
244
462
  if (resolvedHash !== tokensHash) {
@@ -478,8 +696,8 @@ async function runWriteProbes(options) {
478
696
  }
479
697
 
480
698
  // src/doctor/run.ts
481
- import { existsSync as existsSync2, readFileSync as readFileSync3 } from "fs";
482
- import { join as join2 } from "path";
699
+ import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
700
+ import { join as join3 } from "path";
483
701
  var STATIC_API = record("static.api", 1);
484
702
  var STATIC_BOARD = record("static.board", 1);
485
703
  var STATIC_SKILLS = record("static.skills", 1);
@@ -545,8 +763,8 @@ var SKILL_ROOTS = [
545
763
  ".cursor/skills"
546
764
  ];
547
765
  function checkSkillsFreshness(projectRoot) {
548
- const roots = SKILL_ROOTS.map((root) => join2(projectRoot, root)).filter(
549
- (root) => existsSync2(root)
766
+ const roots = SKILL_ROOTS.map((root) => join3(projectRoot, root)).filter(
767
+ (root) => existsSync3(root)
550
768
  );
551
769
  if (roots.length === 0) {
552
770
  return STATIC_SKILLS(
@@ -559,10 +777,10 @@ function checkSkillsFreshness(projectRoot) {
559
777
  const seen = /* @__PURE__ */ new Set();
560
778
  for (const root of roots) {
561
779
  for (const skill of corpus.skills) {
562
- const copied = join2(root, skill.name, "SKILL.md");
563
- if (!existsSync2(copied)) continue;
780
+ const copied = join3(root, skill.name, "SKILL.md");
781
+ if (!existsSync3(copied)) continue;
564
782
  seen.add(skill.name);
565
- if (readFileSync3(copied, "utf8") !== skill.content) {
783
+ if (readFileSync4(copied, "utf8") !== skill.content) {
566
784
  stale.add(skill.name);
567
785
  }
568
786
  }
@@ -612,6 +830,12 @@ async function runDoctor(options) {
612
830
  results.push(
613
831
  ...checkThemeFreshness(options.projectRoot ?? process.cwd(), boardContext)
614
832
  );
833
+ results.push(
834
+ ...checkCookieCodecConformance(options.projectRoot ?? process.cwd())
835
+ );
836
+ results.push(
837
+ envOk ? await checkSandboxPersonaGate(fetchImpl, env, boardContext) : skipSandboxPersonaGate("env checks failed \u2014 fix them first")
838
+ );
615
839
  results.push(
616
840
  ...options.frontendUrl ? await runReadProbes(fetchImpl, options.frontendUrl) : skipReadProbes("no --frontend <url> given")
617
841
  );
@@ -1,6 +1,6 @@
1
1
  import { B as BoardLabelOverrides } from './ui-copy-CKfFTtLk.mjs';
2
- import { J as JobSort, E as EmploymentType, R as RemoteOption, S as Seniority } from './jobs-DPPA1Nev.mjs';
3
- import './_spec-DxC1ze93.mjs';
2
+ import { J as JobSort, E as EmploymentType, R as RemoteOption, S as Seniority } from './jobs-BhthvMkA.mjs';
3
+ import './_spec-l_596ZwW.mjs';
4
4
 
5
5
  declare const REMOTE_OPTIONS: readonly RemoteOption[];
6
6
  /**
package/dist/filters.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { B as BoardLabelOverrides } from './ui-copy-CKfFTtLk.js';
2
- import { J as JobSort, E as EmploymentType, R as RemoteOption, S as Seniority } from './jobs-CLLIvtMc.js';
3
- import './_spec-DxC1ze93.js';
2
+ import { J as JobSort, E as EmploymentType, R as RemoteOption, S as Seniority } from './jobs-CXudz1Y4.js';
3
+ import './_spec-l_596ZwW.js';
4
4
 
5
5
  declare const REMOTE_OPTIONS: readonly RemoteOption[];
6
6
  /**
package/dist/format.d.mts CHANGED
@@ -1,8 +1,8 @@
1
- import { P as PublicJob, a as PublicJobCard, C as CustomFieldValues } from './jobs-DPPA1Nev.mjs';
1
+ import { P as PublicJob, a as PublicJobCard, C as CustomFieldValues } from './jobs-BhthvMkA.mjs';
2
2
  import { B as BoardLabelOverrides } from './ui-copy-CKfFTtLk.mjs';
3
3
  export { A as AlertsCopy, a as ApplyCopy, b as BlogCopy, c as BreadcrumbsCopy, C as CopyLinkCopy, E as EntityCopy, F as FooterCopy, J as JobCardCopy, d as JobDetailCopy, e as JobSearchCopy, N as NavCopy, P as PUBLIC_LABEL_GROUPS, f as PaginationCopy, S as SalaryCopy, U as UiCopy, u as uiCopy } from './ui-copy-CKfFTtLk.mjs';
4
- import { C as CustomFieldDefinition } from './board-CqYibYUA.mjs';
5
- import './_spec-DxC1ze93.mjs';
4
+ import { C as CustomFieldDefinition } from './board-CyHA6rRP.mjs';
5
+ import './_spec-l_596ZwW.mjs';
6
6
 
7
7
  /**
8
8
  * Date display helpers in the board language (required leading parameter,
package/dist/format.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { P as PublicJob, a as PublicJobCard, C as CustomFieldValues } from './jobs-CLLIvtMc.js';
1
+ import { P as PublicJob, a as PublicJobCard, C as CustomFieldValues } from './jobs-CXudz1Y4.js';
2
2
  import { B as BoardLabelOverrides } from './ui-copy-CKfFTtLk.js';
3
3
  export { A as AlertsCopy, a as ApplyCopy, b as BlogCopy, c as BreadcrumbsCopy, C as CopyLinkCopy, E as EntityCopy, F as FooterCopy, J as JobCardCopy, d as JobDetailCopy, e as JobSearchCopy, N as NavCopy, P as PUBLIC_LABEL_GROUPS, f as PaginationCopy, S as SalaryCopy, U as UiCopy, u as uiCopy } from './ui-copy-CKfFTtLk.js';
4
- import { C as CustomFieldDefinition } from './board-RfZEAJse.js';
5
- import './_spec-DxC1ze93.js';
4
+ import { C as CustomFieldDefinition } from './board-BzK5j73O.js';
5
+ import './_spec-l_596ZwW.js';
6
6
 
7
7
  /**
8
8
  * Date display helpers in the board language (required leading parameter,
package/dist/index.d.mts CHANGED
@@ -1,11 +1,11 @@
1
- import { S as Schemas, c as components } from './_spec-DxC1ze93.mjs';
2
- import { F as FetchOptions, c as StorageMode, B as BoardRequest, A as Awaitable, L as Logger, d as BoardClient, a as SearchSuggestQuery } from './search-CqBa1Qc4.mjs';
3
- export { e as ACCESS_TOKEN_KEY, f as BOARD_ACCESS_GRANT_KEY, C as CompanySuggestion, g as CustomStorage, R as REFRESH_TOKEN_KEY, b as SuggestResult, S as SuggestionItem, T as TermSuggestion } from './search-CqBa1Qc4.mjs';
4
- export { C as CustomFieldDefinition, a as CustomFieldOption, b as CustomFieldType, P as PublicBoard, c as PublicBoardAnalytics, d as PublicBoardFeatures, e as PublicBoardTheme } from './board-CqYibYUA.mjs';
5
- import { R as RemoteOption, E as EmploymentType, S as Seniority, L as ListEnvelope, b as JobsListQuery, c as JobCardListEnvelope, d as JobsSearchBody, e as JobCardSearchEnvelope, f as JobsSimilarQuery, g as SearchEnvelope } from './jobs-DPPA1Nev.mjs';
6
- export { h as CustomFieldValue, C as CustomFieldValues, i as EducationRequirement, j as JobCatalogPagination, k as JobCompany, J as JobSort, O as OfficeLocation, l as OffsetPagination, P as PublicJob, a as PublicJobCard, m as RelatedSearch, n as RemotePermit, o as RemoteTimezone, p as StorefrontPagination } from './jobs-DPPA1Nev.mjs';
7
- import { b as CompaniesListQuery, c as CompanyListEnvelope, d as CompaniesSearchBody, e as CompanyJobsListQuery, f as CompanySimilarQuery, g as CompanyMarketsListQuery, h as SalaryDetailQuery, i as BlogPostsListQuery, j as BlogSimilarQuery, k as BlogSearchBody } from './salaries-Rb5h_eVZ.mjs';
8
- export { B as BlogAuthorEmbed, l as BlogTagEmbed, C as CompanyCategorySalary, m as CompanyMarket, n as CompanyMarketRef, a as CompanySalary, L as LocationSalaryDetail, o as LocationSkillsIndex, p as LocationTitlesIndex, q as PublicBlogAdjacentPosts, r as PublicBlogAuthor, s as PublicBlogPost, P as PublicBlogPostSummary, t as PublicBlogTag, u as PublicCompany, v as PublicCompanyDetail, w as SalaryCompany, x as SalaryLocation, y as SalarySkill, z as SalaryTitle, A as SkillLocationSalary, D as SkillLocationsIndex, S as SkillSalaryDetail, E as TitleLocationSalary, F as TitleLocationsIndex, T as TitleSalaryDetail } from './salaries-Rb5h_eVZ.mjs';
1
+ import { S as Schemas, c as components } from './_spec-l_596ZwW.mjs';
2
+ import { F as FetchOptions, c as StorageMode, B as BoardRequest, A as Awaitable, L as Logger, d as BoardClient, a as SearchSuggestQuery } from './search-CrIlXSJP.mjs';
3
+ export { e as ACCESS_TOKEN_KEY, f as BOARD_ACCESS_GRANT_KEY, C as CompanySuggestion, g as CustomStorage, R as REFRESH_TOKEN_KEY, b as SuggestResult, S as SuggestionItem, T as TermSuggestion } from './search-CrIlXSJP.mjs';
4
+ export { C as CustomFieldDefinition, a as CustomFieldOption, b as CustomFieldType, P as PublicBoard, c as PublicBoardAnalytics, d as PublicBoardFeatures, e as PublicBoardTheme } from './board-CyHA6rRP.mjs';
5
+ import { R as RemoteOption, E as EmploymentType, S as Seniority, L as ListEnvelope, b as JobsListQuery, c as JobCardListEnvelope, d as JobsSearchBody, e as JobCardSearchEnvelope, f as JobsSimilarQuery, g as SearchEnvelope } from './jobs-BhthvMkA.mjs';
6
+ export { h as CustomFieldValue, C as CustomFieldValues, i as EducationRequirement, j as JobCatalogPagination, k as JobCompany, J as JobSort, O as OfficeLocation, l as OffsetPagination, P as PublicJob, a as PublicJobCard, m as RelatedSearch, n as RemotePermit, o as RemoteTimezone, p as StorefrontPagination } from './jobs-BhthvMkA.mjs';
7
+ import { b as CompaniesListQuery, c as CompanyListEnvelope, d as CompaniesSearchBody, e as CompanyJobsListQuery, f as CompanySimilarQuery, g as CompanyMarketsListQuery, h as SalaryDetailQuery, i as BlogPostsListQuery, j as BlogSimilarQuery, k as BlogSearchBody } from './salaries-Dr_Zugal.mjs';
8
+ export { B as BlogAuthorEmbed, l as BlogTagEmbed, C as CompanyCategorySalary, m as CompanyMarket, n as CompanyMarketRef, a as CompanySalary, L as LocationSalaryDetail, o as LocationSkillsIndex, p as LocationTitlesIndex, q as PublicBlogAdjacentPosts, r as PublicBlogAuthor, s as PublicBlogPost, P as PublicBlogPostSummary, t as PublicBlogTag, u as PublicCompany, v as PublicCompanyDetail, w as SalaryCompany, x as SalaryLocation, y as SalarySkill, z as SalaryTitle, A as SkillLocationSalary, D as SkillLocationsIndex, S as SkillSalaryDetail, E as TitleLocationSalary, F as TitleLocationsIndex, T as TitleSalaryDetail } from './salaries-Dr_Zugal.mjs';
9
9
 
10
10
  /**
11
11
  * Well-known `<domain>_<snake_reason>` codes the Board API sends, grouped by
@@ -141,7 +141,7 @@ declare function paginate<Q extends Record<string, unknown>, P extends PageShape
141
141
  * constant because the package is platform-neutral and cannot read
142
142
  * package.json at runtime.
143
143
  */
144
- declare const SDK_VERSION = "1.39.0";
144
+ declare const SDK_VERSION = "1.41.0";
145
145
 
146
146
  type SavedJob = Schemas['SavedJob'];
147
147
  type SavedJobsListQuery = {
@@ -257,6 +257,12 @@ type CreateCompanyBody = Schemas['CreateCompanyBody'];
257
257
  type UpdateEmployerCompanyBody = Schemas['UpdateEmployerCompanyBody'];
258
258
  type SendWorkEmailBody = Schemas['SendWorkEmailBody'];
259
259
  type ConfirmWorkEmailBody = Schemas['ConfirmWorkEmailBody'];
260
+ /**
261
+ * The viewer's per-employer talent entitlement from
262
+ * `board.me.talentAccess.retrieve` — the talent-CTA signal (sourced from the
263
+ * same subscription/credit-pack truth the talent paywall enforces).
264
+ */
265
+ type TalentAccess = Schemas['TalentAccess'];
260
266
  /** Query for `board.me.companies.search`. */
261
267
  type EmployerCompanySearchQuery = {
262
268
  q: string;
@@ -274,6 +280,25 @@ type EmployerJobsListQuery = {
274
280
  /** 1–200 (default 200). */
275
281
  limit?: number;
276
282
  };
283
+ /**
284
+ * One job's reporting funnel from `board.me.companies.jobStats.retrieve`.
285
+ * `views` / `applyClicks` degrade to `0` on a Tinybird outage (the endpoint
286
+ * never fails on analytics), so a `0` is "no activity" OR "analytics briefly
287
+ * unavailable". `applications` is `null` for an external-apply job.
288
+ */
289
+ type EmployerJobStat = Schemas['EmployerJobStat'];
290
+ /**
291
+ * One daily bucket from `board.me.companies.jobStats.timeseries`, aggregated
292
+ * across the company's jobs. Zero-filled over the window, ascending by date.
293
+ */
294
+ type EmployerJobStatsPoint = Schemas['EmployerJobStatsPoint'];
295
+ /** Query for `board.me.companies.jobStats.timeseries`. */
296
+ type EmployerJobStatsTimeseriesQuery = {
297
+ /** Inclusive window start (ISO 8601). Defaults to 30 days before `until`. */
298
+ since?: string;
299
+ /** Exclusive window end (ISO 8601). Defaults to now. */
300
+ until?: string;
301
+ };
277
302
  /** A job's full applicant pipeline (job header + stage rail + applicants). */
278
303
  type EmployerPipeline = Schemas['EmployerPipeline'];
279
304
  /** One applicant on a job's pipeline, with its activity timeline. */
@@ -657,6 +682,8 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
657
682
  publicJobSubmission: boolean;
658
683
  candidatePaywall: boolean;
659
684
  impressum: boolean;
685
+ nativeApplications: boolean;
686
+ messaging: boolean;
660
687
  };
661
688
  talentDirectoryVisibility: "off" | "public" | "employers_only";
662
689
  analytics: {
@@ -1506,6 +1533,19 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
1506
1533
  };
1507
1534
  }>;
1508
1535
  cancelClaim(slug: string, options?: FetchOptions): Promise<void>;
1536
+ retrieve(slug: string, options?: FetchOptions): Promise<{
1537
+ id: string;
1538
+ object: "employer_company";
1539
+ name: string;
1540
+ slug: string;
1541
+ website: string | null;
1542
+ description: string | null;
1543
+ summary: string | null;
1544
+ xUrl: string | null;
1545
+ linkedinUrl: string | null;
1546
+ facebookUrl: string | null;
1547
+ logoUrl: string | null;
1548
+ }>;
1509
1549
  update(slug: string, body: UpdateEmployerCompanyBody, options?: FetchOptions): Promise<{
1510
1550
  id: string;
1511
1551
  object: "employer_company";
@@ -1519,6 +1559,19 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
1519
1559
  facebookUrl: string | null;
1520
1560
  logoUrl: string | null;
1521
1561
  }>;
1562
+ uploadLogo(slug: string, file: Blob, options?: FetchOptions): Promise<{
1563
+ id: string;
1564
+ object: "employer_company";
1565
+ name: string;
1566
+ slug: string;
1567
+ website: string | null;
1568
+ description: string | null;
1569
+ summary: string | null;
1570
+ xUrl: string | null;
1571
+ linkedinUrl: string | null;
1572
+ facebookUrl: string | null;
1573
+ logoUrl: string | null;
1574
+ }>;
1522
1575
  workEmail: {
1523
1576
  verify(slug: string, body: SendWorkEmailBody, options?: FetchOptions): Promise<{
1524
1577
  id: string;
@@ -1822,6 +1875,21 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
1822
1875
  renewsAt: string | null;
1823
1876
  }>>;
1824
1877
  };
1878
+ jobStats: {
1879
+ retrieve(slug: string, options?: FetchOptions): Promise<ListEnvelope<{
1880
+ object: "employer_job_stat";
1881
+ jobId: string;
1882
+ views: number;
1883
+ applyClicks: number;
1884
+ applications: number | null;
1885
+ }>>;
1886
+ timeseries(slug: string, query?: EmployerJobStatsTimeseriesQuery, options?: FetchOptions): Promise<ListEnvelope<{
1887
+ object: "employer_job_stats_point";
1888
+ date: string;
1889
+ views: number;
1890
+ applyClicks: number;
1891
+ }>>;
1892
+ };
1825
1893
  applicants: {
1826
1894
  list(slug: string, query: EmployerPipelineQuery, options?: FetchOptions): Promise<{
1827
1895
  object: "employer_pipeline";
@@ -1846,6 +1914,15 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
1846
1914
  reorder(slug: string, body: ReorderPipelineStagesBody, options?: FetchOptions): Promise<void>;
1847
1915
  };
1848
1916
  };
1917
+ talentAccess: {
1918
+ retrieve(options?: FetchOptions): Promise<{
1919
+ object: "talent_access";
1920
+ isEmployer: boolean;
1921
+ paywallActive: boolean;
1922
+ hasTalentAccess: boolean;
1923
+ hasUnlimitedUnlocks: boolean;
1924
+ }>;
1925
+ };
1849
1926
  alerts: {
1850
1927
  list(options?: FetchOptions): Promise<ListEnvelope<{
1851
1928
  id: string;
@@ -2883,6 +2960,7 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
2883
2960
  title: string;
2884
2961
  companyName: string;
2885
2962
  companyUrl: string | null;
2963
+ companyLogoUrl: string | null;
2886
2964
  location: string | null;
2887
2965
  employmentType: string | null;
2888
2966
  locationType: string | null;
@@ -2895,6 +2973,7 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
2895
2973
  education: {
2896
2974
  institutionName: string;
2897
2975
  institutionUrl: string | null;
2976
+ institutionLogoUrl: string | null;
2898
2977
  degree: string | null;
2899
2978
  fieldOfStudy: string | null;
2900
2979
  grade: string | null;
@@ -2923,4 +3002,4 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
2923
3002
  };
2924
3003
  type BoardSdk = ReturnType<typeof createBoardClient>;
2925
3004
 
2926
- export { type AccessCheckoutBody, type AccessCheckoutSession, type AccessCheckoutSessionState, type AccessGrant, type AccessPortalBody, type AccessPortalSession, type AddApplicantNoteBody, type Alert, type AlertBody, type Application, type ApplicationsListQuery, type ApplyAction, type ApplyBody, Awaitable, BOARD_API_ERROR_CODES, type Block, type BlockStatus, type BlockUserBody, type BlockedUser, BlogPostsListQuery, BlogSearchBody, BlogSimilarQuery, type BoardAccessGrant, BoardApiError, type BoardApiErrorCode, type BoardAuthSession, BoardClient, BoardRequest, type BoardSdk, type BoardSeo, type BoardUser, type BulkMoveApplicantsBody, type BulkRejectApplicantsBody, type CandidateAvatar, type CandidateEducation, type CandidateExperience, type CandidateLanguage, type CandidateProfile, type CandidateSkill, type ClaimableCompany, CompaniesListQuery, CompaniesSearchBody, CompanyJobsListQuery, CompanyListEnvelope, CompanyMarketsListQuery, type CompanyMembership, CompanySimilarQuery, type ConfirmWorkEmailBody, type ConsumeMagicLinkBody, type Conversation, type ConversationArchive, type ConversationDetail, type ConversationRef, type ConversationsListQuery, type CreateBoardClientOptions, type CreateCompanyBody, type CreateEducationBody, type CreateEmployerJobBody, type CreateExperienceBody, type CreateJobPostingInput, type CreatePipelineStageBody, type EditMessageBody, type EmbedJobsQuery, type EmployerApplicant, type EmployerBillingOption, type EmployerCheckout, type EmployerCheckoutBody, type EmployerCompany, type EmployerCompanySearchQuery, type EmployerJob, type EmployerJobSummary, type EmployerJobsListQuery, type EmployerPipeline, type EmployerPipelineQuery, type EmployerPipelineStage, EmploymentType, FetchOptions, type FindExistingConversationQuery, type ForgotPasswordBody, type HandleAvailability, type JobAlertConfirmation, type JobAlertDeletePreferenceInput, type JobAlertFiltersInput, type JobAlertFrequency, type JobAlertManageQuery, type JobAlertManageResult, type JobAlertManageState, type JobAlertManageTokenInput, type JobAlertPreference, type JobAlertRemoteOption, type JobAlertResendResult, type JobAlertStoredFilters, type JobAlertSubscribeInput, type JobAlertSubscription, type JobAlertUpdatePreferenceInput, JobCardListEnvelope, JobCardSearchEnvelope, type JobPostingBillingOptions, type JobPostingBillingVerification, type JobPostingLogoResult, type JobPostingPlan, type JobPostingResult, JobsListQuery, JobsSearchBody, JobsSimilarQuery, type LegalEntity, type LegalPageType, ListEnvelope, Logger, type LoginBody, type LogoutBody, type Message, type ModerationReport, type MoveApplicantStageBody, type NotificationPreference, type OAuthAuthorizationQuery, type OAuthAuthorizationUrl, type OAuthExchangeBody, type OAuthProvider, type Paginator, type PaywallOffer, type PaywallOfferListEnvelope, type PlacesListQuery, type Plan, type PlanListEnvelope, type PlansListQuery, type PublicLegalPage, type PublicPlace, type PublicTaxonomyTerm, type ReadReceipt, type RedirectResolution, type RefreshBody, type RegisterBody, RemoteOption, type RemotePermitTaxonomyEntry, type ReorderPipelineStagesBody, type ReplyBody, type ReportBody, type RequestMagicLinkBody, type ResetPasswordBody, type Resume, type ResumeUploadOptions, SDK_VERSION, SalaryDetailQuery, type SalesLedPlan, type SalesLedPlanListEnvelope, type SaveJobBody, type SavedJob, type SavedJobsListQuery, SearchEnvelope, SearchSuggestQuery, type SendWorkEmailBody, Seniority, type StartAboutApplicationBody, type StartConversationBody, StorageMode, type SuggestionsListQuery, type TalentDirectoryEntry, type TalentDirectoryListEnvelope, type TalentDirectoryQuery, type TalentProfile, type TaxonomyGeo, type TaxonomyListQuery, type TaxonomyResolution, type ThreadMessagesQuery, type UnreadCount, type UnsubscribeBody, type UpdateApplicationFactsBody, type UpdateCandidateProfileBody, type UpdateEducationBody, type UpdateEmployerCompanyBody, type UpdateEmployerJobBody, type UpdateExperienceBody, type UpdateLanguagesBody, type UpdateNotificationPreferenceBody, type UpdatePipelineStageBody, type UpdateSkillsBody, type VerifyEmailBody, createBoardClient, isBoardApiError, isBoardPasswordRequired, isColdRule, isConflict, isForbidden, isNotFound, isOwnMessage, isRateLimited, isSafeApplicationUrl, isUnauthorized, isValidationError, lastOwnMessageId, paginate, resolveApplyAction };
3005
+ export { type AccessCheckoutBody, type AccessCheckoutSession, type AccessCheckoutSessionState, type AccessGrant, type AccessPortalBody, type AccessPortalSession, type AddApplicantNoteBody, type Alert, type AlertBody, type Application, type ApplicationsListQuery, type ApplyAction, type ApplyBody, Awaitable, BOARD_API_ERROR_CODES, type Block, type BlockStatus, type BlockUserBody, type BlockedUser, BlogPostsListQuery, BlogSearchBody, BlogSimilarQuery, type BoardAccessGrant, BoardApiError, type BoardApiErrorCode, type BoardAuthSession, BoardClient, BoardRequest, type BoardSdk, type BoardSeo, type BoardUser, type BulkMoveApplicantsBody, type BulkRejectApplicantsBody, type CandidateAvatar, type CandidateEducation, type CandidateExperience, type CandidateLanguage, type CandidateProfile, type CandidateSkill, type ClaimableCompany, CompaniesListQuery, CompaniesSearchBody, CompanyJobsListQuery, CompanyListEnvelope, CompanyMarketsListQuery, type CompanyMembership, CompanySimilarQuery, type ConfirmWorkEmailBody, type ConsumeMagicLinkBody, type Conversation, type ConversationArchive, type ConversationDetail, type ConversationRef, type ConversationsListQuery, type CreateBoardClientOptions, type CreateCompanyBody, type CreateEducationBody, type CreateEmployerJobBody, type CreateExperienceBody, type CreateJobPostingInput, type CreatePipelineStageBody, type EditMessageBody, type EmbedJobsQuery, type EmployerApplicant, type EmployerBillingOption, type EmployerCheckout, type EmployerCheckoutBody, type EmployerCompany, type EmployerCompanySearchQuery, type EmployerJob, type EmployerJobStat, type EmployerJobStatsPoint, type EmployerJobStatsTimeseriesQuery, type EmployerJobSummary, type EmployerJobsListQuery, type EmployerPipeline, type EmployerPipelineQuery, type EmployerPipelineStage, EmploymentType, FetchOptions, type FindExistingConversationQuery, type ForgotPasswordBody, type HandleAvailability, type JobAlertConfirmation, type JobAlertDeletePreferenceInput, type JobAlertFiltersInput, type JobAlertFrequency, type JobAlertManageQuery, type JobAlertManageResult, type JobAlertManageState, type JobAlertManageTokenInput, type JobAlertPreference, type JobAlertRemoteOption, type JobAlertResendResult, type JobAlertStoredFilters, type JobAlertSubscribeInput, type JobAlertSubscription, type JobAlertUpdatePreferenceInput, JobCardListEnvelope, JobCardSearchEnvelope, type JobPostingBillingOptions, type JobPostingBillingVerification, type JobPostingLogoResult, type JobPostingPlan, type JobPostingResult, JobsListQuery, JobsSearchBody, JobsSimilarQuery, type LegalEntity, type LegalPageType, ListEnvelope, Logger, type LoginBody, type LogoutBody, type Message, type ModerationReport, type MoveApplicantStageBody, type NotificationPreference, type OAuthAuthorizationQuery, type OAuthAuthorizationUrl, type OAuthExchangeBody, type OAuthProvider, type Paginator, type PaywallOffer, type PaywallOfferListEnvelope, type PlacesListQuery, type Plan, type PlanListEnvelope, type PlansListQuery, type PublicLegalPage, type PublicPlace, type PublicTaxonomyTerm, type ReadReceipt, type RedirectResolution, type RefreshBody, type RegisterBody, RemoteOption, type RemotePermitTaxonomyEntry, type ReorderPipelineStagesBody, type ReplyBody, type ReportBody, type RequestMagicLinkBody, type ResetPasswordBody, type Resume, type ResumeUploadOptions, SDK_VERSION, SalaryDetailQuery, type SalesLedPlan, type SalesLedPlanListEnvelope, type SaveJobBody, type SavedJob, type SavedJobsListQuery, SearchEnvelope, SearchSuggestQuery, type SendWorkEmailBody, Seniority, type StartAboutApplicationBody, type StartConversationBody, StorageMode, type SuggestionsListQuery, type TalentAccess, type TalentDirectoryEntry, type TalentDirectoryListEnvelope, type TalentDirectoryQuery, type TalentProfile, type TaxonomyGeo, type TaxonomyListQuery, type TaxonomyResolution, type ThreadMessagesQuery, type UnreadCount, type UnsubscribeBody, type UpdateApplicationFactsBody, type UpdateCandidateProfileBody, type UpdateEducationBody, type UpdateEmployerCompanyBody, type UpdateEmployerJobBody, type UpdateExperienceBody, type UpdateLanguagesBody, type UpdateNotificationPreferenceBody, type UpdatePipelineStageBody, type UpdateSkillsBody, type VerifyEmailBody, createBoardClient, isBoardApiError, isBoardPasswordRequired, isColdRule, isConflict, isForbidden, isNotFound, isOwnMessage, isRateLimited, isSafeApplicationUrl, isUnauthorized, isValidationError, lastOwnMessageId, paginate, resolveApplyAction };