Company-scope resolution auto-attaches by normalised key, but #765 and company-key.ts say the key only suggests
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Refactor
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- typescript
- Domain
- backend-api-design, documentation, frontend
Research direction
Start by comparing #765 with src/lib/storage/company-key.ts:14-19, then inspect src/lib/letters/resolve-letter.ts and src/lib/resume/resolve-variant.ts alongside PRs #906 and #983. Decide whether company matches auto-attach or require confirmation; done means #765, the docblock, both resolver docblocks, and the relevant UI or tests consistently enforce the chosen contract.
Written by the indexing model from the issue text.
Description
Problem
The three-tier artifact epic (#765) and its child issues disagree about what a company key is allowed to do.
The written contract says the key only suggests. #765, section "Company identity: never inferred, always confirmed":
the normaliser only ever suggests ("You have a letter for Northwind — start from it?"), and the user picks. A false merge is then a suggestion declined, not a letter silently attached to the wrong employer.
src/lib/storage/company-key.ts:14-19 on main says the same thing:
The key is advisory. Per #765 it only ever drives a suggestion the user confirms … Nothing here auto-attaches a letter to a job, which is what makes a collision affordable … Treat a match as evidence, never as identity.
The resolution chains attach by key automatically. #767 and #770 both specify a job → company → standard chain where the company rung matches by deriveCompanyKey(job.company) === record.companyKey, and nobody confirms the match:
src/lib/letters/resolve-letter.ts(PR #906):inheritedLetterForJobreturns any company letter whose key matches.src/lib/resume/resolve-variant.ts(PR #983):resolveVariantForJobdoes the same for résumé variants. #770 AC "Download PDF renders the resolved variant for a job in context" then exports that variant.
Failing case
- A user creates a company variant for job A at "Acme Co" (a staffing firm). It is stored with
companyKey: "acme". - The user saves job B at "Acme, Inc." (a different employer).
deriveCompanyKeymaps both names to"acme". - Job B resolves to the Acme Co variant with
scope: "company". The Download PDF for job B is the résumé tailored for the staffing firm, and the user never confirmed the match.
Under the #765 rule, the worst outcome of this collision was supposed to be a suggestion the user declines. Under the chains, it is a résumé or letter silently attached to the wrong employer: the exact outcome #765 names as the one to avoid. The scope label ("company") reports which rung the chain used. It does not tell the user that the match is only a guess.
Why this needs a decision rather than a patch
Both readings are defensible:
- The chain is right, and the contract text is stale. Once a user has explicitly created a company-scoped artifact, applying it to the same company is the whole point of that scope. The #765 rule was written for the start-from suggestion and never updated when #767/#770 made company scope load-bearing. Fix: amend #765 and the
company-key.tsdocblock to say resolution does attach by key. Say what makes that acceptable (for example, the scope label and a visible company name), and note the collision risk the docblock currently calls affordable. - The contract is right, and the chains overreach. The company rung stays a suggestion. The first time a job resolves to a company artifact, the UI asks "Use your Acme Co variant for Acme, Inc.?", and resolution reads that confirmation.
Right now main says one thing, and two open PRs implement the other.
Proposed fix
Decide which reading is right, then make #765, company-key.ts and both resolver docblocks say the same thing. If the confirm reading wins, add the confirmation to the #767 and #770 UI steps before their export and reveal surfaces land.
Acceptance criteria
- #765's "Company identity" section and the
company-key.tsdocblock describe what the resolution chains actually do - If auto-attach is kept: the docblock states the collision risk plainly instead of calling it affordable, and the UI shows the job's company name next to the company scope label
- If confirm-first is chosen: neither chain returns a
companyresolution for a job whose match the user has not confirmed, and a test pins this for both lanes
Found while reviewing #983.
- Dominant language
- TypeScript
- Stars
- 11
- Forks
- 4
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 40
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from offlinecv/OfflineCV
-
chore
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
testing
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
improvement ux:edit-export
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
refactor testing
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
chore
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
All issues in offlinecv/OfflineCV
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
receptron/mulmoterminal#2264 ·
-
documentation
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
components-web-app/docs#96 ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
simonsobs/tileviewer#114 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100