Skip to content

Employer administrators cannot create ats_job (403 PERMISSION_DENIED) even with the stamps fixed — the insert-side RLS check is compiled without the membership resolver's keys and evaluated on the pre-hook payload (upstream) #45

Description

@os-sam

Found while delivering #43 (branch claude/issue-43-stamp-hook-parent-lookup, main 068c7c3, cli 17.3.0). Filed unassigned and unlabelled for triage. Not a defect in the stamp hooks and not fixable from src/hooks/ or src/security/; the two mechanisms are in plugin-security and are filed there.

Blocked-by: objectstack-ai/objectstack#16607
Blocked-by: objectstack-ai/objectstack#16608

Measured, same identity (admin@quillstone.example), fixed hooks, both drivers

write result
POST /api/v1/data/ats_job (employer = Quillstone's id, no employer_org) 403 PERMISSION_DENIED
POST /api/v1/data/ats_job WITH employer_org: org_ats_quillstone 403 PERMISSION_DENIED
PATCH /api/v1/data/ats_job/ID on one of Quillstone's jobs 200
POST /api/v1/data/ats_employer_member WITH employer_org: org_ats_quillstone 201
POST /api/v1/data/ats_employer_member WITHOUT employer_org (left to the stamp) 403 PERMISSION_DENIED

The first bare job insert logs [RLS] DENY (fail closed): policy 'employer_admin_jobs' on 'ats_job' ... (check clause, unresolved-variable): variable "current_user.employer_org_ids" is undefined; every attempt logs [Security] RLS check FAILED on insert 'ats_job' — write denied (fail-closed).

The two halves

  1. objectstack#16607computeWriteCheckFilter never calls stageRlsMembership, so on a bare insert the resolver-published employer_org_ids (DESIGN.md §03, Employer-side RLS policies fail closed for everyone: IN (current_user.accessible_org_ids) is the deprecated SQL-style spelling and the bridge cannot bind the variable #18) is unresolved and the check fails closed. The rows that pass above do so because an earlier read on the same request context staged the key by accident (the update's pre-image read; the master read a controlled_by_parent insert performs).
  2. objectstack#16608 — the insert check's post-image is the raw payload evaluated before beforeInsert, so a field the stamp writes (employer_org, candidate_user) never counts on insert; the caller would have to send the value the stamp exists to make un-sendable.

What this means for the repository

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions