Commit graph

3 commits

Author SHA1 Message Date
sjcoetzeesj-coder
cd0a818641 feat(cipc): director appointment check tab
Reconcile CIPC BizPortal against the Workflow database for every
director ID number we hold, and report only the two kinds of
difference that need a decision:

  1. new appointment  - CIPC lists the person as a director of company
     X, the database does not.
  2. no longer a director - the database lists the person at company X,
     CIPC no longer shows them there.

Everything that is in sync is not reported, so the list stays short
enough to work through by hand.

- New page /cipc-report with an explorer that runs the check, polls
  the run and lists the exceptions.
- New API route /api/cipc/report: POST starts a background batch run
  of the existing "Bizportal Directopr id no search.py" (invoked
  exactly as it already behaves, including its own login rotation),
  GET returns run status and the exception lists. ?demo=1 returns a
  fixed sample so the screen can be shown without a live run.
- New action route /api/cipc/report/action for the per-exception
  follow-up actions.
- scripts/cipc-report/build_report.py renders the run into a PDF with
  the exceptions marked, plus the sample report used by ?demo=1.

The BizPortal tooling only exists on the Windows dev machine, so like
the other CIPC routes this tab cannot run the live search from the
Coolify Linux image.
2026-10-27 12:19:47 +02:00
sjcoetzeesj-coder
92dcae5122 fix(cipc): stop deadlocking wrapper on agent-browser daemon start
runAb() in scripts/_cipc_service.js resolved only on proc.on('close'),
but agent-browser is a daemon-per-session CLI. When it has to START the
session browser daemon (first call after a reboot, after the daemon died,
or after the app restarts), the new daemon inherits the spawned CLI
stdout pipe. The pipe then never reaches EOF, so Node 'close' event
never fires - even though the CLI exited cleanly with code 0. The 30s
timeout in runAb called proc.kill(SIGTERM), but the process had already
exited, so the kill was a no-op and the promise never settled. The
wrapper serialised mutex then held inFlight forever, every later request
queued behind it, and CIPC search silently 500-ed for days with no log
line to show why - which is what made this look like a flaky / restart-
only issue.

Fixes:
  - runAb now settles on 'exit' (with a 250ms flush grace for stdio to
    drain), escalates the timeout kill to SIGKILL, and guarantees an
    unconditional forced settle if neither fires. The promise can no
    longer remain pending.
  - app/api/cipc/search/route.ts: ensureWrapperService() now probes port
    6002 on every search and respawns the wrapper (rate-limited to once
    per 30s) if it is down. Hot reloads still no-op once a wrapper is up,
    but a dead wrapper now self-heals instead of 500-ing forever.

Verified end to end: killed the browser daemon and the wrapper, started
a fresh wrapper, its first isWarm() spawned a new daemon (the previous
deadlock path) and returned in under 1s. A real enterprise search of
K2018435959 came back in 31.7s on the cold path and 50.9s on the warm
path with full company + director data.
2026-10-19 13:40:36 +02:00
sjcoetzeesj-coder
11d0178ab1 feat: commit Workflow app source; move CIPC credentials to env
Adds the full Next.js app (app/, components/, lib/, scripts/, assets/,
docs/, Dockerfile, compose, configs) to version control.

Security:
- CIPC BizPortal customer-code logins (Login 1 + Login 3) now read
  CIPC_LOGIN1_CODE / CIPC_LOGIN1_PASSWORD / CIPC_LOGIN3_CODE /
  CIPC_LOGIN3_PASSWORD from .env.local instead of source.
- BizPortal personal login in apply-bizportal route reads
  BIZPORTAL_ID_NO / BIZPORTAL_PASSWORD.
- Added .env.example as the committed template.

.gitignore excludes .env*, node_modules, .next, logs, sqlite, Playwright
storage_state.json (live CIPC cookies), scratch dirs, client PDFs and
debug screenshots.
2026-10-18 15:21:45 +02:00