Measured while delivering #67 on claude/issue-67-employer-contact, base c3c6526. #67 fixes exactly
one column (ats_employer.owner) with a stored name mirror, because that mirror is only defensible
where the audience already holds the fact. The other five Field.user columns have no such mirror
and are unfixed; this card is the general case.
What was measured
One container, objectstack dev -p 4671, demo seed (818 rows, errored: 0), both drivers, counted
after [Seeder] Seed loading complete with hasMore == false and records.length == total asserted.
sys_user rows readable per persona — identical on the memory and the sqlite driver:
| Persona |
sys_user readable |
of the 30 employer-staff rows |
admin@platform.example |
1 of 113 |
0 |
ops@platform.example |
1 of 113 |
0 |
candidate01@mail.example |
1 of 113 |
0 |
admin@objectos.ai (platform owner, no ATS position) |
113 of 113 |
30 |
The one row each persona reads is its own. "Employer staff" is not a hand-written set: it is the 30
user values of ats_employer_member, read as the platform owner.
Consequence, as admin@platform.example, one request per row (populate on the field):
ats_candidate.user -> ["usr_ats_c45","usr_ats_c08","usr_ats_c04"]
ats_interview.interviewers -> [["usr_ats_swiftroute_r1"],["usr_ats_harborline_r1","usr_ats_harborline_admin"], …]
ats_offer.approved_by -> ["usr_ats_cedarbrook_admin","usr_ats_cedarbrook_admin","usr_ats_summitridge_admin"]
ats_report.reporter -> ["usr_ats_c06","usr_ats_brightmarket_r1","usr_ats_c61"]
ats_employer_member.user -> ["usr_ats_lumenvale_r2","usr_ats_summitridge_r2","usr_ats_pixelforge_admin"]
Not one of them expands. ats_interview.interviewers is an authored grid column
(src/views/interview.view.ts), so a platform reviewer reads that queue as a column of raw ids —
the same defect #67 measured on ats_employer.owner, on a surface #67 does not touch.
Why this is a change and not the known state
#67's triage comment measured the same thing on 54cd69c and got 83 of 113 readable — 80
candidates, 2 platform staff, the dev owner — and recorded ats_candidate.user expanding correctly:
Avery Lindqvist user = {"id":"usr_ats_c01","name": …} <- expanded
Today that same field is a bare usr_ats_c45. The readable set has gone 83 -> 1 and a field that
resolved a name now does not. The merges between 54cd69c and c3c6526 that touch membership are
#38 and #79 (membershipPolicy invite-only). The cause was not traced — this card reports the
measurement and the interval, not a mechanism.
Why the #67 fix does not generalise
#67 stamps owner_name from sys_user.name because a platform reviewer already reads those same 12
names on ats_employer_member.display_name, so the mirror restates a fact rather than disclosing
one; the job-seeker set seals it for the audience that holds no such fact. Neither half of that
argument is available for ats_candidate.user or ats_interview.interviewers — there is no second
column already telling a platform reviewer those names. Mirroring them would be a new disclosure, so
the choice here is a real one: either a platform persona is allowed to resolve the users it already
governs, or these columns keep rendering ids.
Related: #67 (the one column with a mirror), #39, #30, #35.
Measured while delivering #67 on
claude/issue-67-employer-contact, basec3c6526. #67 fixes exactlyone column (
ats_employer.owner) with a stored name mirror, because that mirror is only defensiblewhere the audience already holds the fact. The other five
Field.usercolumns have no such mirrorand are unfixed; this card is the general case.
What was measured
One container,
objectstack dev -p 4671, demo seed (818rows,errored: 0), both drivers, countedafter
[Seeder] Seed loading completewithhasMore == falseandrecords.length == totalasserted.sys_userrows readable per persona — identical on the memory and the sqlite driver:sys_userreadableadmin@platform.exampleops@platform.examplecandidate01@mail.exampleadmin@objectos.ai(platform owner, no ATS position)The one row each persona reads is its own. "Employer staff" is not a hand-written set: it is the 30
uservalues ofats_employer_member, read as the platform owner.Consequence, as
admin@platform.example, one request per row (populateon the field):Not one of them expands.
ats_interview.interviewersis an authored grid column(
src/views/interview.view.ts), so a platform reviewer reads that queue as a column of raw ids —the same defect #67 measured on
ats_employer.owner, on a surface #67 does not touch.Why this is a change and not the known state
#67's triage comment measured the same thing on
54cd69cand got 83 of 113 readable — 80candidates, 2 platform staff, the dev owner — and recorded
ats_candidate.userexpanding correctly:Today that same field is a bare
usr_ats_c45. The readable set has gone 83 -> 1 and a field thatresolved a name now does not. The merges between
54cd69candc3c6526that touch membership are#38 and #79 (
membershipPolicyinvite-only). The cause was not traced — this card reports themeasurement and the interval, not a mechanism.
Why the #67 fix does not generalise
#67 stamps
owner_namefromsys_user.namebecause a platform reviewer already reads those same 12names on
ats_employer_member.display_name, so the mirror restates a fact rather than disclosingone; the job-seeker set seals it for the audience that holds no such fact. Neither half of that
argument is available for
ats_candidate.userorats_interview.interviewers— there is no secondcolumn already telling a platform reviewer those names. Mirroring them would be a new disclosure, so
the choice here is a real one: either a platform persona is allowed to resolve the users it already
governs, or these columns keep rendering ids.
Related: #67 (the one column with a mirror), #39, #30, #35.