job-pro 1.0.20 → 1.0.21

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 (2) hide show
  1. package/dist/index.js +47 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -178,6 +178,7 @@ VERBS (same surface for every company)
178
178
  --batch <file|-> apply to many post_ids (one/line)
179
179
  --debug-submit-to <url> verify wire format
180
180
  --really-submit actually fire (env-gated)
181
+ --allow-stale-session bypass 30-day session-age gate
181
182
  memory list | get <k> | set k=v | event <kind> [payload] | clear
182
183
 
183
184
  OUTPUT
@@ -637,6 +638,20 @@ async function runCompany(adapter, company, rawArgs) {
637
638
  const result = await submitApplication(staged, { kind: "debug", url: debugUrl });
638
639
  return emit({ mode: "debug-submit", staged, submit_kind: kindForDebug, result }, compact);
639
640
  }
641
+ // Session staleness gate (applies to any --really-submit that uses a
642
+ // captured session). Sessions for non-anon adapters generally expire
643
+ // around the 30-day mark; firing a stale cookie just nets a 401 with
644
+ // no diagnostic. Catch it before the submit fires.
645
+ const allowStaleSession = args.includes("--allow-stale-session");
646
+ const maxAgeDays = Number(process.env.JOB_PRO_SESSION_MAX_AGE_DAYS ?? 30);
647
+ function sessionAgeDays(s) {
648
+ if (!s?.exported_at)
649
+ return null;
650
+ const ts = Date.parse(s.exported_at);
651
+ if (!Number.isFinite(ts))
652
+ return null;
653
+ return Math.floor((Date.now() - ts) / 86_400_000);
654
+ }
640
655
  // --really-submit: actually hit the upstream endpoint. Guarded by both
641
656
  // an env-var attestation and (for non-anon adapters) a session.json.
642
657
  if (reallySubmit) {
@@ -707,6 +722,22 @@ async function runCompany(adapter, company, rawArgs) {
707
722
  `log in to the careers site, click Export.`,
708
723
  }, compact);
709
724
  }
725
+ const age = sessionAgeDays(session);
726
+ if (age !== null && age > maxAgeDays && !allowStaleSession) {
727
+ return emit({
728
+ ok: false,
729
+ source: company,
730
+ post_id: postId,
731
+ mode: "really-submit-blocked",
732
+ staged,
733
+ submit_kind: kind,
734
+ session_age_days: age,
735
+ message: `session at ~/.jobpro/${company}.session.json is ${age} days old (limit ${maxAgeDays}); ` +
736
+ `careers-site sessions usually expire around 30d and a stale cookie would yield ` +
737
+ `an inscrutable 401. Re-capture via the extension, or pass --allow-stale-session ` +
738
+ `(also: JOB_PRO_SESSION_MAX_AGE_DAYS env).`,
739
+ }, compact);
740
+ }
710
741
  const result = await familyExecutor(staged, session, { kind: "upstream" });
711
742
  return emit({ mode: "really-submit", staged, submit_kind: kind, session_used: true, result }, compact);
712
743
  }
@@ -740,6 +771,22 @@ async function runCompany(adapter, company, rawArgs) {
740
771
  `then mv ~/Downloads/jobpro/${company}.session.json ~/.jobpro/`,
741
772
  }, compact);
742
773
  }
774
+ if (!isAnonMultipart) {
775
+ const age = sessionAgeDays(session);
776
+ if (age !== null && age > maxAgeDays && !allowStaleSession) {
777
+ return emit({
778
+ ok: false,
779
+ source: company,
780
+ post_id: postId,
781
+ mode: "really-submit-blocked",
782
+ staged,
783
+ submit_kind: kind,
784
+ session_age_days: age,
785
+ message: `session at ~/.jobpro/${company}.session.json is ${age} days old (limit ${maxAgeDays}); ` +
786
+ `re-capture via the extension or pass --allow-stale-session.`,
787
+ }, compact);
788
+ }
789
+ }
743
790
  const result = await submitApplication(staged, { kind: "upstream" }, { session });
744
791
  return emit({ mode: "really-submit", staged, submit_kind: kind, session_used: !!session, result }, compact);
745
792
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "job-pro",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "description": "Query Chinese big-tech campus recruiting from your terminal. 50 companies, all 50 live. 46 via each company's own API; the 4 with no public canonical feed (Hikvision, CICC, Cainiao, WeBank) surfaced via Liepin as a clearly-labeled third-party fallback. No signup, no token, no server.",
5
5
  "homepage": "https://job.ha7ch.com",
6
6
  "repository": "https://github.com/HA7CH/job-pro",