16 KiB
International Job Discovery Implementation Plan
For agentic workers: Use superpowers:executing-plans to implement this plan task-by-task only after explicit stage authorization. Delegation is not required by this plan. Do not start implementation from this document alone.
Goal: Deliver cross-industry, multilingual NO/SE/GB discovery while preserving Jobjakt's current data and document owners.
Architecture: Extend existing React/MUI discovery, .NET services and MariaDB. Use a source-rights registry, NAV local index, eligible live-query adapters and honest external/manual fallbacks; no generative model dependency.
Tech stack: React 19/Next.js static shell, TypeScript, MUI, ASP.NET/EF Core 9, MariaDB, existing background services and test tools.
Spec: Master, separate GJ-01–08 prompts, architecture/contracts, acceptance.
Global constraints
- Planning only now; Phase 10, PRODUCT-REVIEW-01, initiative approval and next-stage instruction precede implementation.
- No main merge, production operation, destructive data change, restricted scraping, consumer registration or paid-resource purchase.
- Preserve Career Profile, CV Import/Editor, applications, frozen packages, revisions, histories, all 57 groups/33 routes and MariaDB compatibility.
- Never enable live AI without independent qualification; core suggestions/matching are deterministic.
- Each stage stops after acceptance and publication. Later source branch includes accepted predecessors. Stage prompts override this proposed file breakdown if they conflict.
- Run
graphify querybefore code exploration, trace every shared caller before changes, andgraphify update .after code changes (no update needed for this docs-only stage).
Review focus
- Legacy FINN URL preview reaches HTML fetch before plugin selection: GJ04-F must deny it before network while keeping reviewed manual entry usable.
- A withdrawn source moves location or loses fields: GJ04-G must remove it independent of old/new query filters and surviving duplicate sources.
- Parent remains checked after town refinement: GJ02-C/D must query only refinements and roundtrip exact scope state.
- Search edited/deleted while worker is sending: GJ06-B must recheck revision/owner/status and suppress obsolete delivery, including restart.
- Source-content purge and user application evidence differ: GJ06-D/GJ07-C must enforce approved retention without deleting user notes or silently changing frozen history.
Execution and evidence pattern
For each checkpoint below: record exact source/callers and baseline → add the specified failing contract/scenario test → run and preserve RED → make smallest complete change → run focused checks then required stage regressions → review diff/security/rights → document measured outcomes, commit/push only its authorized branch and verify remote HEAD → stop at stage end. Do not count focused reruns twice. New fixtures are synthetic or lawfully retained/redacted; no private CVs or credentials in evidence.
Representative existing commands (verify local SDK/package scripts/config at entry): rtk dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter FullyQualifiedName~JobDiscovery, rtk npm test -- --runInBand job-discovery.test.tsx from UI, and configured Playwright discovery specs. These are planned commands, not executed results. MariaDB uses the repository's existing isolated integration lane after its entry check; do not start Docker/DB or tests with unknown live service targets. TypeScript/lint/build and ordinary/separate browser lanes use current package scripts and explicit configs, serialized with PDF/build lanes. Capture native exits and discovery membership.
GJ-01 — preferences and languages
Branch feature/gj01-country-language-preferences; authority GJ-01. Entry: all global gates above. Produces SearchPreference contract and persisted locale/default semantics from ADR-03.
Files: extend JobTrackerApi/Models/ApplicationUser.cs, Controllers/AuthController.cs, Data/JobTrackerContext.cs; proposed Models/SearchPreference.cs, preference controller/service and additive migration. Extend job-tracker-ui/src/components/SettingsView.tsx, views/JobDiscoveryPage.tsx, i18n/I18nProvider.tsx, i18n/translations.ts, api.ts/types where existing ownership requires. Test proposed SearchPreferenceTests.cs, UI preference/locale tests, existing settings e2e and account export/deletion contracts.
- GJ01-A: freeze DTO/schema validation, expected revision and empty legacy defaults; RED cross-owner/missing-owner/concurrent-write/old-account tests, then additive persistence. No schema deletions.
- GJ01-B: first-run/Settings defaults and optional residence distinct from work countries; test cross-device recovery and no nationality collection.
- GJ01-C: locale registry/native labels/prominence/Coming Later/fallback; complete required translations and missing-key checks; native language review stays separate.
- GJ01-D: initialize draft query from defaults, explicit Update defaults/save named profile boundary; test temporary overrides never persist accidentally. Named rich saved-search lifecycle is completed in GJ-06 using same query contract.
- GJ01-E: tenant/export/delete/revision/EN-Bokmål regressions and approved shipped-locale proof. Publish
docs/global-jobs/01/acceptance and stop. Unqualified Swedish UI journey remains blocked, not silently counted passing.
GJ-02 — geography
Branch feature/gj02-geographic-search; GJ-02. Consumes preferences; produces LocationNode, LocationScope, LocationQueryPlan contracts from ADR-03/geography decisions.
Files: proposed Models/DiscoveryLocation.cs, Services/Discovery/LocationScopeCompiler.cs, versioned reference importer under existing tooling conventions, Controllers/DiscoveryLocationsController.cs, EF mapping/migration, src/components/discovery/LocationScopePicker.tsx and shared discovery query types. Test LocationScopeCompilerTests.cs, MariaDB mapping/index tests, UI scope transitions, browser discovery specs.
- GJ02-A: obtain exact licensed snapshots/IDs/geometries, especially Warwick town versus district and overlapping SE/NO settlements. Block precise town query if no qualified footprint exists.
- GJ02-B: idempotent versioned import + typed relations/provider mapping + stale-ID review; tests prove no orphan/broadened saved scopes and no partial dataset swap.
- GJ02-C: implement scope/refinement controls; test every geography decision-table transition, collapse/save/reload and accessible announcements.
- GJ02-D: compile exact IDs/polygons, radius/multi-origin/remote rules; assert county-only job fails strict town/radius filter and out-of-parent radius result is disclosed.
- GJ02-E: measured lookup/query/load, keyboard/mobile/zoom tests and edition/licence ledger. Publish
docs/global-jobs/02/and stop.
GJ-03 — occupations
Branch feature/gj03-occupation-search; GJ-03. Consumes query/scopes; produces OccupationConcept/OccupationQueryPlan, without AI.
Files: proposed Models/DiscoveryOccupation.cs, Services/Discovery/OccupationQueryCompiler.cs, versioned dataset importer, Controllers/DiscoveryOccupationsController.cs, src/components/discovery/OccupationAutocomplete.tsx; integrate JobDiscoveryPage, preserve JobImport/SkillTagger.cs callers. Test taxonomy/alias/compiler suites and browser combobox fixtures.
- GJ03-A: licence/checksum/version manifest for ESCO/SSYK/SOC, reviewed aliases/crosswalk relation types and frozen ten-sector/three-language benchmark; approve metrics before measuring.
- GJ03-B/C: concept lookup and accessible cancellable typeahead; test stale response, same word/different language, deprecated ID and taxonomy outage.
- GJ03-D: exact/related/keyword modes, optional skill chips and provider mapping; test “weekend work”, free text and no qualification inference.
- GJ03-E: report per-sector/language precision/recall and p95/index size; publish
docs/global-jobs/03/and stop.
GJ-04 — providers and inventory
Branch feature/gj04-provider-connectors; GJ-04. Consumes canonical query/location/occupation plans; produces source-aware DiscoveryPageV1 and permitted detail/lifecycle data.
Files: existing Controllers/JobDiscoveryController.cs, Services/JobDiscoverySearchService.cs, Services/JobImport/JobImportService.cs, Plugins/FinnPlugin.cs; proposed Services/Discovery/ProviderRightsPolicy.cs, DiscoveryQueryService.cs, Providers/ capability-specific adapters, inventory/cursor models, EF mappings/migrations and DI registration at current host owner. Tests extend JobDiscoveryControllerTests, JobImportServiceTests, transport tests and proposed provider/lifecycle/dedupe MariaDB tests.
- GJ04-A: reverify matrix, exact API schemas/grants, numeric cache/quota/lag policy and credential references; unknown capability denied. Test every denied mode and rights expiry/revocation before adapter work.
- GJ04-B: inventory/event/cursor transaction, replay/out-of-order/crash/bootstrap/backoff tests; additive migration and search compatibility adapter.
- GJ04-C: NAV ingestion only with consumer authorization; fixtures can proceed independently, clearly labelled. Test removal/masking independent of area and no public-token production fallback.
- GJ04-D: SE JobSearch and truncated JobAd Links, exact taxonomy IDs and bounded windows; original-link/completeness/404/429 tests. JobStream only after separately qualified need.
- GJ04-E: licensed GB adapter or explicit external-link-only state; do not mark a fixture connector live. No full Adzuna body reconstruction.
- GJ04-F: FINN URL recognition/bookmark/manual workflow with zero network fetch through both new and existing import entry points; test malicious hosts, redirects and approved-source exceptions.
- GJ04-G: conservative dedupe, source loss and field-rights lineage, SSRF/XSS/rate/rights tests; separately bounded approved live contracts. Publish
docs/global-jobs/04/with provider-by-provider decisions and stop.
GJ-05 — unified discovery UI
Branch feature/gj05-discovery-ui; GJ-05. Consumes page/detail contracts; produces desktop/mobile results/detail and existing workflow actions.
Files: extend views/JobDiscoveryPage.tsx, App.tsx routes, existing PageLayout/theme/API/types; proposed components/discovery/JobDetailPanel.tsx and filter/list pieces only when independently needed. Reuse existing job dialog/actions. Extend src/job-discovery.test.tsx, e2e/job-discovery.spec.ts, e2e/phase7-discovery.spec.ts.
- GJ05-A/B: filter rail/list/detail with independent partial-source/loading/error/empty states; tests preserve draft filters, deep link/history and return focus.
- GJ05-C: results/query semantics, sorting/pagination, exact-filter coverage and conservative alternate-source grouping; test stale/partial-source results and missing fields.
- GJ05-D: render full/truncated/link-only details with safe HTML/plain-text fallback, salary period/prediction/unknown fields and provenance. Assert blocked content never appears in DOM/API/export.
- GJ05-E: reviewed Save/Track/original-apply actions and native CV/letter document links, with AI gated.
- GJ05-F: phone full-screen details, tablet/desktop, EN/Bokmål and qualified locales, keyboard/zoom/themes, accessibility/fidelity/regression. Publish
docs/global-jobs/05/, exact visual/axe/manual limits and stop.
GJ-06 — searches, alerts and matches
Branch feature/gj06-alerts-matching; GJ-06. Consumes permitted inventory/query and existing profile/application owners; produces revision-safe SavedSearch, SavedJob, SearchAlert behavior.
Files: extend Models/SavedJobSearch.cs, Services/SavedJobSearchRunner.cs, SavedJobSearchAlertHostedService.cs, Controllers/JobDiscoveryController.cs, owned export/deletion services; proposed bookmark/subscription/delivery models and deterministic match service; UI search profile/notification/actions; no parallel application/profile writer. Tests SavedJobSearchAlertTests, SavedJobSearchSqliteTests, account export/deletion, MariaDB races and browser tracking/documents.
- GJ06-A: versioned full queries, duplicate/edit/delete/suspend/restore and legacy bare-NAV-ID migration; test revision conflict and exact scope roundtrip.
- GJ06-B: durable delivery/initial baseline/frequency/DST/pause/unsubscribe/deduplication; test duplicate workers, crash, changed/deleted search, withdrawn job before dispatch, source stale, overlapping searches and ambiguous mail send failure.
- GJ06-C: evidence-backed occupation/skills/qualification explanations; tests include nurse licence absent, cleaner empty profile, language unknown and profile revision change.
- GJ06-D: Save distinct from Track, idempotent tracked link, CV/letter native workflow; assert no canonical/CV/frozen-package mutation from source update and approved purge policy behavior.
- GJ06-E: security/fanout/accessibility/retention checks; publish
docs/global-jobs/06/and stop.
GJ-07 — admin and resilience
Branch feature/gj07-discovery-operations; GJ-07. Consumes feed/alert state; produces admin health, redacted correlation diagnostics and incident/rollback runbooks.
Files: extend Controllers/AdminSystemController.cs, src/views/AdminSystemPage.tsx, existing operation response/presentation contracts where appropriate; proposed system source-sync state/log projection (not synthetic tenant user), rights/retention controls. Tests admin API/UI, provider failure drills, export/delete/restore and resource limits.
- GJ07-A/B: provider rights/access/health/quota/lag/cursor/backlog/count metrics and paginated correlation events; distinguish actual system sync from real submitting user.
- GJ07-C: Admin check on every list/detail/stream/export; assert tenant/non-admin denial, redaction, no unsafe HTML/PII/raw Docker logs, retained source purge and account erasure.
- GJ07-D: provider loss, invalid schema, repeated cursor, credential revocation, index outage, lease expiry, retry storm and bounded load; verify backup/restore suppression and additive rollback. No production maintenance dispatch. Publish
docs/global-jobs/07/and stop.
GJ-08 — integrated acceptance
Branch test/gj08-global-discovery-acceptance; GJ-08. Entry: actual GJ-01–07 accepted ancestry, rights scope and source freeze, not sum of stage test counts.
- GJ08-A: freeze integrated source/config/fixture/dataset/licence identity and discover exact full-suite membership; reconcile blocked capabilities.
- GJ08-B: run all matrix journeys, backend/frontend/browser/contracts/actual MariaDB/model-disabled sidecar where applicable, TypeScript/lint/build and unchanged preservation/PDF oracles. Serialize build/browser/PDF lanes; retain native exits and failures.
- GJ08-C: authorised provider smoke separately from fixtures; per-country/source/content/language/geographic coverage report. Complete human/device/native-language/AT/print checks only with real evidence, otherwise OPEN.
- GJ08-D: source lifecycle/security/load/rollback/release gate review; publish
docs/global-jobs/08/, per-stage/provider development decisions and production NO-GO unless separately authorized and qualified. Commit/push and stop; never deploy or merge main.